使用CMAKE過程中碰到的棧溢位問題總結
最近在Linux開發中使用CMKE自動生成makefile,程式執行中碰到了棧溢位的問題(實際還不太確定是不是stack overflow problem導致),於是花了很多時間細細研究了記憶體劃分及分配等相關機制,感覺瞭解比以前透徹了不少,在此做一下先總結一下問題及解決方法以及還存在的疑問。
碰到的問題
先說一下碰到的問題:我們在Linux下寫的程式,是一個龐大的系統,一個程序下啟用了超過30個執行緒同時執行,某個執行緒中一個函式體內聲明瞭一個大概8KB大小的陣列。在原先自己寫的Makefile編譯執行都正常,但是採用Cmake的方式自動生成makefile,編譯通過,執行的時候每次都會出現segmentation fault,backtrace顯示被呼叫函式的入參都為0,但是上一級函式傳入引數的時候,所有引數都是有值的。一進入被呼叫函式,就出現了core dump,gdb backtrace顯示程式掛在了被呼叫函式的第一行。
解決辦法
碰到該問題,現象有些詭異,函式呼叫前的入參都是有值的,一進入函式,就都變成了0。經過長時間的debug,最後確定是函式內申請的8KB陣列導致的segfault。因此推斷是陣列導致棧溢位,覆蓋了入參的值(不確定是否最終原因)。但是Linux系統預設的程序棧大小為8MB,嘗試用ulimit -s 調整棧大小為16MB,仍然沒有解決問題,按理說,8KB的陣列並不大,但是如果將8KB分配在棧上的陣列改成malloc動態分配的方式,segfault就消失了。所以解決辦法就是將函式中超過1KB的陣列都該成從堆上分配空間。
但是改解決辦法雖然解決了出現的問題,但是還是無法解釋心中的疑問:
1. 為什麼8KB的陣列會導致segmentation fault?
2. 如果8KB的陣列造成了棧溢位從而導致segmentation fault,為何調整棧大小為原來的兩倍,遠遠超過陣列大小時,仍然沒解決問題?
3. 另外就是CMAKE生成的makefile,gcc引數幾乎跟自己寫的makefile上的引數一樣,但是原來的makfile下build的程式能夠正常的執行,通過CMAKE生成makefile並build的程式卻通不過,CMAKE是否有預設的設定導致程式使用的棧更小?
重新分析源程式,上面的問題又更清晰一些了。
出現segmentation fault的函式是線上程中執行的,而執行緒擁有自己獨立的棧,共享程序所擁有的資源,這裡需要區分一下執行緒棧與程序棧兩個概念,雖然執行緒共享程序的資源(程序虛擬地址空間等
至於使用CMAKE與不使用CMAKE自動生成makefile所build 的程式執行結果為什麼不同,只能猜測也許有個別引數的差異導致兩者分別build出的程式執行緒棧大小有差異吧,希望有CMAKE專家指點迷津。