2013-08-01 31 views
0

我正在將一個已經在Windows和Linux中運行的程序移植到MacOS(Lion),並且遇到了一個非常奇怪的問題。在MacOS上的gcc:奇怪的線程錯誤

我有一個很長的函數(大約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或連接發生停止錯誤。 (它向下移動了幾行,遠低於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; 

任何想法可能在這裏發生的事情會非常歡迎。稍後我會嘗試將該功能拆分成更小的部分,以查看是否有幫助(這可能是因爲堆棧問題)。

+0

「* ...如果我刪除幾行代碼,它只是向下移動一點。*「你wa nt說:「* ...了一下。*」不是嗎? – alk

+0

'loudness_on'和'en'是局部變量還是全局變量?它後者是否保護它們免受併發訪問? – alk

+0

我真的不明白:「*從這一行刪除loudness_on或en可以防止發生錯誤。*」所以它停止發生,很好。但是,等等,它不會「*(它向下移動幾行,遠低於en2超出範圍的點)。」什麼東西向下移動?錯誤發生的地方? – alk

回答

1

我找到了解決方案:如果我用更大的堆棧創建pthread,它不會再崩潰。我必須說gdb-warning很不明確,似乎根本沒有指出堆棧空間用完了(調試器應該能夠檢測到這個問題嗎?)

無論如何,這段代碼解決了這個問題:

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上並行線程默認堆棧大小隻有512 KB(在Linux上它是8 MB!) - 此代碼是增加了1.5 MB(1人可能已經足夠了,但是由於發生的錯誤真的很奇怪,我想避免在將來再做一次搜索,我給它多一點。)