0

我正在将一个已经在 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;

任何想法可能会在这里发生将非常受欢迎。稍后我将尝试将函数拆分为更小的部分,看看是否有帮助(如果它是堆栈问题可能会)。

4

1 回答 1

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 可能就足够了,但由于发生的错误真的很奇怪并且我想避免将来不得不进行另一次搜索,我会提供更多。)

于 2013-08-02T14:06:56.393 回答