启动新线程后的Segfault

时间:2011-07-21 12:19:13

标签: c gcc pthreads segmentation-fault

我正在编写一个股票市场系统,它使用多个线程来处理收到的订单。

项目进展顺利,直到我再添加一个帖子。当我启动所述线程我的程序段错误。通过无效的内存读取在上述线程中生成段错误。

当使用优化-O2及更高版本编译程序时,此仅生成

使用-g3使用调试信息编译编程并使用

运行valgrind
valgrind ./marketSim

并获得有关segfault的以下输出

==2524== Thread 5:
==2524== Invalid read of size 4
==2524==    at 0x402914: limitWorker (limit.c:4)
==2524==    by 0x4E33D5F: start_thread (in /lib/libpthread-2.14.so)
==2524==  Address 0x1c is not stack'd, malloc'd or (recently) free'd
==2524== 
==2524== 
==2524== Process terminating with default action of signal 11 (SIGSEGV)
==2524==  Access not within mapped region at address 0x1C
==2524==    at 0x402914: limitWorker (limit.c:4)
==2524==    by 0x4E33D5F: start_thread (in /lib/libpthread-2.14.so)

线程像这样启动

pthread_t limit_thread;
pthread_create(&limit_thread, NULL, limitWorker, q);

q是变量,它也传递给我初始化的其他线程

limitWorker代码如下

void *limitWorker(void *arg){
    while(1){
        if ((!lsl->empty) && (!lbl->empty)) {
            if ((currentPriceX10 > lGetHead(lsl)->price1) && (currentPriceX10 < lGetHead(lbl)->price1)) {
                llPairDelete(lsl,lbl);
            }
        }
    }
    return NULL;
}

第4行:根据valgrind产生段错误的行是void *limitWorker(void *arg){

还有一些更多的信息是使用gcc 4.6.1编译的,当使用gcc 4.1.2时,程序不会出现段错误,即使它已经过优化,尽管它的性能要差得多。

使用clang编译程序时,优化时也不会出现段错误。

问题

我犯了错误吗?这是一个gcc bug吗?我应该采取什么行动?

如果你想查看代码,那么github页面是https://github.com/spapageo/Stock-Market-Real-Time-System/

相关代码位于文件marketSim.climit.c

编辑: Valgrind指定无效读取发生在第4行。第4行是函数的“头部”。我不知道编译器内部,所以我天真的想法是,这个论点是错误的。 在segfault参数之后使用gdb时,因为程序已经优化,is optimized out根据gdb。所以我不认为那是罪魁祸首。

1 个答案:

答案 0 :(得分:7)

如果要编译64位系统,则0x1cprice1结构中order字段的偏移量。这意味着当发生故障时,lsl->HEADlbl->HEAD中的任何一个(或两个)都是NULL指针。

请注意,因为limitWorker()函数在llPairDelete()函数之外不包含线程同步,所以它是不正确的,并且编译器可能不会在每次执行循环时重新加载这些值。即使在只读路径中,您也应该使用互斥锁来保护链接列表

此外,您的lsllbl变量是多重定义的。您应该在extern中将其声明为limit.h,并在extern中没有limit.c的情况下定义它们。