C 启动新线程后的Segfault

C 启动新线程后的Segfault,c,gcc,pthreads,segmentation-fault,C,Gcc,Pthreads,Segmentation Fault,我正在编写一个股票市场系统,它使用几个线程来处理传入的订单 项目进展顺利,直到我又添加了一个线程。当我启动上述线程时,我的程序会出现故障。segfault是在上述线程中由无效内存读取生成的 只有在使用optimization-O2和更高版本编译程序时,才会生成此segfault 在使用-g3编译带有调试信息的编程并使用 valgrind ./marketSim 并获得以下关于segfault的输出 ==2524== Thread 5: ==2524== Invalid read of size

我正在编写一个股票市场系统,它使用几个线程来处理传入的订单

项目进展顺利,直到我又添加了一个线程。当我启动上述线程时,我的程序会出现故障。segfault是在上述线程中由无效内存读取生成的

只有在使用optimization-O2和更高版本编译程序时,才会生成此segfault

在使用-g3编译带有调试信息的编程并使用

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;
}
void*limitWorker(void*arg){
而(1){
如果((!lsl->empty)&(!lbl->empty)){
如果((当前价格x10>lGetHead(lsl)->price1)和&(当前价格x10price1)){
llPairDelete(lsl,lbl);
}
}
}
返回NULL;
}
第4行:根据valgrind产生segfault的行是
void*limitWorker(void*arg){

还有一些更多的信息,这是使用GCC4.6.1编译的,当使用GCC4.1.2时,程序不会出错,即使经过优化,尽管它的性能要差得多

当使用
clang
编写程序时,优化后也不会出现故障

问题

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

如果您想查看代码,github页面是

问题代码位于文件
marketSim.c
limit.c


EDIT:Valgrind指定无效读取发生在第4行。第4行是“头”我不知道编译器的内部结构,所以我天真的认为参数是错误的。但是在使用gdb时,在segfult参数之后,因为程序是优化的,
根据gdb进行了优化。
。所以我不认为这是罪魁祸首。

如果您是为64位系统编译,那么en
0x1c
order
结构中
price1
字段的偏移量。这意味着发生故障时
lsl->HEAD
lbl->HEAD
中的一个(或两个)是空指针

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


此外,您的
lsl
lbl
变量是多重定义的。您应该在
limit.h
中声明它们为
extern
,并在
limit.c
中定义它们而不使用
extern
,我想您已经搞定了。是的,我是在64位系统中编译的。我认为第一个if子句
if((!lsl->empty)和&(!lbl->empty))
可以防止我在第二个if
if((currentPriceX10>lGetHead(lsl)->price1)和&(currentPriceX10price1))处超过空指针
但是编译器的优化和预加载让我很为难。而且我也不知道如何声明
lsl
lbl
内部包含的防护装置aka
#ifndef LIMIT\u H
与extern语句不同,因为它们都是为我工作的。@Spyros:按照您的方式,每个
.c
文件都包含
limit.h
定义这些变量,这意味着您最终会得到多个定义。这是不允许的,具体发生什么取决于您的链接器如何处理它-只是不要这样做。@Spyros:AFAIK,include-guards在同一文件中保存您的多个声明,但是如果您想访问在中定义的变量,则需要extern另一个文件。@puffadder我猜,链接器为我处理了副本。Thx为提示。