Thread 2 “ThreadPool.out“ received signal SIGSEGV, Segmentation fault.关于空指针解引用引起的段错误异常

问题背景:

        最近在学习Linux的多线程和线程池,在调试用C写的一段线程池代码的过程中,出现了一个错误(只截了关键部分):

Thread 2 “ThreadPool.out“ received signal SIGSEGV, Segmentation fault.关于空指针解引用引起的段错误异常_第1张图片

Thread 2 "ThreadPool.out" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7ffff77c2700 (LWP 4298)]
0x00005555555555fa in manager (arg=0x0) at /home/syl/projects/ThreadPool/threadpool.c:246
246        while (!pool->shutdown)
Segmentation fault

 大意是说在246行的while (!pool->shutdown)处出现了段错误。(图中是修改过的所以显示250,可忽略)

这里说明一下246行附近写了什么:

void* manager(void* arg)
{
	ThreadPool* pool = (ThreadPool*)arg;
	while (!pool->shutdown)                    // 246行处
	{
        ...
    }
    return NULL;
}



首先来了解一下什么是段错误。(懂的可以略过)

段错误(Segmentation Fault),通常简称为"segfault",是指当程序访问了一个无效的内存地址或者试图对只读内存进行写操作时,操作系统会终止程序的执行并抛出段错误异常。

段错误通常是由以下情况引起的:

  1. 空指针解引用:当程序试图对空指针进行解引用操作,即访问空指针指向的内存地址时,会导致段错误。
  2. 访问越界:当程序访问了超出分配给它的内存范围的地址或数组的越界索引时,会导致段错误。
  3. 写入只读内存:当程序试图向只读内存地址写入数据时,如字符串常量,会导致段错误。
  4. 栈溢出:当程序的栈空间超过了系统所允许的最大限制,会导致栈溢出,进而产生段错误。

段错误的发生会导致程序崩溃,可能会导致进程异常终止。它是一种严重的错误,常常表示程序中存在错误的内存访问行为,如指针错误、内存越界等。调试和修复段错误通常需要定位错误发生的位置,并检查程序中的内存操作、指针使用等问题。使用调试工具(如GDB)和良好的编程实践可以帮助发现和修复段错误。

 问题解决:


经过和原创者的源代码反复对比,发现线程池创建函数 threadPoolCreate,其中创建线程那里有个函数是:

pthread_create (&pool->managerID, NULL, manager, pool); 

注意pthread_create这个函数的第四个参数是 pool

而我的代码中写的是:

pthread_create (&pool->managerID, NULL, manager, NULL); 

到这里问题的原因就很明显了,我错把第四个参数写成了NULL,这导致了将一个空指针NULL作为参数arg传递给了manager。这相当于245行的

ThreadPool* pool = (ThreadPool*)arg;


将一个空指针赋给了pool,这样在判断while(!pool->shutdown)时,当然会出错啦!

出错的原因也很明显,导致段错误的原因是 pool 变量为 NULL 或未初始化,在尝试访问 pool->shutdown 时会导致无效的内存访问。(空指针解引用引起的段错误)
 

最后修改完之后重新调试,编译成功!

Thread 2 “ThreadPool.out“ received signal SIGSEGV, Segmentation fault.关于空指针解引用引起的段错误异常_第2张图片


 

感谢:


感谢线程池作者爱编程的大丙提供的学习资源

你可能感兴趣的:(服务器,c语言,linux)