今天在給車綜的SDK做測試時,遇到了一個線程崩潰的問題。大概情形是我 用車綜的SDK封裝了一個類,在一個線程中定義了一個這個類的對象,然后再線程啟動的時候,在線程的入口處即導致崩潰。然而以指針的形式來定義則沒有問題。經大神指出是因為每個線程對於所使用的堆棧大小是有限制的,我的這個類對象占用的堆棧超出了限制。
以下資料參考博客關於線程堆棧大小的注意事項
每個線程獨立擁有一個可配置大小的堆棧,一個線程內所有函數使用到的堆棧都依賴於這個棧,如果太多的變量、參數需要使用棧,則可能導致棧溢出。目前基礎平台子系統通過配置環境變量,將默認堆棧大小設置為128K,可以減少這個問題的出現,但業務系統在編碼時仍然 需要注意棧的使用,避免出現問題。
包括:
1、不要在函數內部定義過大的局部變量,如過大的結構體變量,聯合變量,過大的字符串,數組等;
2、函數調用的深度也需要注意,如果函數 A 調用 B, B 再調用 C,而A/B/C每個函數定義了 10 K的局部變量,則總的棧空間需求將超過 30K;
3、不要直接將大的結構變量通過函數參數傳遞,這樣也會消耗棧空間,可以通過指針或者引用的方式傳遞;
4、建議每個函數內部定義的變量大小控制在4-8K以下;
5、如果在運行中 COREDUMP,並且通過 GDB 的 WHERE 命令時看到剛進入某個函數就報錯,連函數內的第一條調試語句都無法指向,則基本可以認為是棧空間不夠導致的,可以嘗試將棧空間配置大一點,如果問題不再出現,則可以確定問題。這時需要按照前面幾點的要求修改代碼,減少棧的使用。
這讓我想起了之前在做英偉達硬解時,在線程內分配顯存會導致崩潰,而把分配顯存移到線程外則沒有問題。大神猜測說是線程對顯存的分配有限制。 在此一並記錄。
另一篇關於修改線程堆棧大小博客設置線程堆棧大小