我正在编写一个股票市场系统,它使用多个线程来处理收到的订单。
项目进展顺利,直到我再添加一个帖子。当我启动所述线程我的程序段错误。通过无效的内存读取在上述线程中生成段错误。
当使用优化-O2及更高版本编译程序时,此
使用-g3使用调试信息编译编程并使用
运行valgrindvalgrind ./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.c
和limit.c
编辑: Valgrind指定无效读取发生在第4行。第4行是函数的“头部”。我不知道编译器内部,所以我天真的想法是,这个论点是错误的。 但在segfault参数之后使用gdb时,因为程序已经优化,is optimized out
根据gdb。所以我不认为那是罪魁祸首。
答案 0 :(得分:7)
如果要编译64位系统,则0x1c
是price1
结构中order
字段的偏移量。这意味着当发生故障时,lsl->HEAD
和lbl->HEAD
中的任何一个(或两个)都是NULL指针。
请注意,因为limitWorker()
函数在llPairDelete()
函数之外不包含线程同步,所以它是不正确的,并且编译器可能不会在每次执行循环时重新加载这些值。即使在只读路径中,您也应该使用互斥锁来保护链接列表。
此外,您的lsl
和lbl
变量是多重定义的。您应该在extern
中将其声明为limit.h
,并在extern
中没有limit.c
的情况下定义它们。