MacOS 上的 gcc:奇怪的线程错误
Posted
技术标签:
【中文标题】MacOS 上的 gcc:奇怪的线程错误【英文标题】:gcc on MacOS: Strange threading error 【发布时间】:2013-08-01 13:59:44 【问题描述】:我正在将一个已经在 Windows 和 Linux 中运行的程序移植到 MacOS (Lion),我遇到了一个非常奇怪的问题。
我有一个很长的函数(大约 3000 行 C++ 代码),如果我直接从我的主线程调用它,它运行良好。
但是,如果我创建一个单独的 pthread 并从那里调用相同的函数,我会崩溃。即使主线程没有做任何事情(睡眠)。崩溃总是发生在完全相同的地方(所以这不是时间问题),这个函数大约有 2000 行;如果我删除几行代码,它只会向下移动一点。
使用 gcc 4.2,错误发生在调试模式下,如果我启用一些优化,错误就会消失(但使用 -O3 会再次发生)。使用 gcc 4.9,如果我启用 -O2 或 -O3,它只会在发布模式下发生。所以,我现在正试图弄清楚 gcc 4.2 会发生什么(因为我可以在调试模式下重现它)。
让事情变得更奇怪:我有 2 个布尔值(loudness_on 和 en),崩溃发生在以下行:
bool en2 = loudness_on && en;
从此行中删除 Loudness_on 或 en 会阻止错误发生。 (它向下移动了几行,远低于 en2 超出范围的点)。
我已经运行了 valgrind,它没有报告任何错误。
我怀疑是堆栈问题(也许线程的堆栈较小?)但 gdb 报告的内容似乎与堆栈无关:
Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0x0000000109588ec7
[Switching to process 12928 thread 0x4203]
0x00000001002e4809 in ParSet::refresh_parameters () at /Users/User/BUILD/Param.cpp: 3017
3017 bool en2 = loudness_on && en;
非常欢迎任何想法在这里可能发生的事情。稍后我会尝试将函数拆分为更小的部分,看看是否有帮助(如果是堆栈问题,可能会有所帮助)。
【问题讨论】:
"...如果我删除几行代码,它只会向下移动一点。" 你想说“...向上一点。 ”你不会吗?loudness_on
和 en
是线程局部变量还是全局变量?后者是您保护它们免受并发访问吗?
我不太明白:“从该行中删除 Loudness_on 或 en 会阻止错误发生。”所以它停止发生了,很好。但是等等,它没有“(它向下移动几行,远低于 en2 超出范围的点)。”向下移动的是什么?发生错误的行?
抱歉不清楚。这两个变量都是函数的局部变量——这就是它如此奇怪的原因。我可以在调试器中毫无问题地查看它们的值。
我的意思是代码仍然在函数中进一步崩溃了几行。
【参考方案1】:
我找到了解决方案:如果我使用更大的堆栈创建 pthread,它不再崩溃。我必须说 gdb 警告非常不清楚,似乎根本没有指出堆栈空间不足(调试器应该能够检测到这一点吗?)
不管怎样,这段代码解决了它:
size_t stacksize = 0;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_getstacksize(&attr, &stacksize);
pthread_attr_setstacksize(&attr, max(stacksize, 1024 * (1024 + 512));
pthread_t wxmt;
pthread_create(&wxmt, &attr, mainThread, NULL);
事实证明,Mac 上 pthreads 的默认堆栈大小仅为 512 kB(在 Linux 上为 8 MB!) - 此代码将其增加到 1.5 MB(1 可能就足够了,但由于发生的错误真的很奇怪,我想避免以后再做一次搜索,我再给它一点。)
【讨论】:
以上是关于MacOS 上的 gcc:奇怪的线程错误的主要内容,如果未能解决你的问题,请参考以下文章
有没有一种方法可以让 OpenMP 在 Qt spanwed 线程上运行?
带有多线程的 Console.ReadKey() 的奇怪行为