工作中遇到這樣一個問題,某個多級流水多線程的程序,在壓力測試下會偶現segmentation fault11錯誤,錯誤出現在運行類函數的地方,而后排查后發現是由於多線程爭搶導致類被析構后才走入判斷,導致出現內存越界。
class A { bool error_; int Reply(); }
Task1.cpp
if (a->process1() != 0) a->error_ = true; if (!a->error_) { do { if (a->process2() != 0) { a->error_ = true; break; }
put_next(a); }while(0); } if (a->error_) { a->Reply(); }
代碼流程如上:
1、多級流水:Task1->Task2->Task3,且每個Task內有多個線程
2、Task1處理完畢后將a放入Task2的消息隊列,此時由於CPU爭搶導致Task1被卡住,未能繼續執行
3、Task2、Task3依次處理完成后,a消息返回給上級模塊,delete a
4、此時Task1獲取到CPU資源,繼續執行
5、而a已被析構,Task1內的a仍舊保存原有指針地址
6、由於a已被析構,a->error_不可預知,進入判斷,走到a->Reply(),然而a已析構,所以崩潰。
總結:多線程程序中線程內和線程間的執行順序不可預知,要確保每個線程內只能有一個終點,盡量避免GOTO或多次判斷導致出現邏輯分支的情況。