[問題] 如何追查可能因MutilThtread下stackover

看板C_and_CPP (C/C++)作者 (為何世界會那麼不單純)時間9月前 (2023/07/23 14:45), 9月前編輯推噓11(11035)
留言46則, 9人參與, 9月前最新討論串1/2 (看更多)
開發平台(Platform): (Ex: Win10, Linux, ...) linux openwrt 編譯器(Ex: GCC, clang, VC++...)+目標環境(跟開發平台不同的話需列出) gcc 額外使用到的函數庫(Library Used): (Ex: OpenGL, ...) 問題(Question): 傳入參數被莫名的修改 某個API 如下 CfaIfmNotifyInterfacStat (u4IfIndex, u1AdminStatus, &u1OperStatus, u1IsFromMib, u1IsRegToIp, &IfInfo)) != CFA_SUCCESS) 傳入時的值: u4IfIndex=43 , u1AdminStatus=1, &u1OperStatus=(UINT1 *) 0xb1e0256f 進入API後值卻變成 https://upload.cc/i1/2023/07/23/ZnvhDF.jpg
u4IfIndex=0, u1AdminStatus=0 , pu1InOperStatus=0x0, 前面4個參數都被變成0 請問各位網友其會被修改到的原因 是不是因為Mutil thread 所造成 其值被其他thread StackOverflow 修改 但由於thread 眾多 各位網友是不是有甚麼的方式或tool 能介紹給我 去debug 找出是哪個thread 哪段code 所造成 謝謝 -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 106.1.107.225 (臺灣) ※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1690094718.A.61A.htmltanted:轉錄至看板 Soft_Job 07/23 14:55

07/23 15:39, 9月前 , 1F
thread很固定的改到別的thread的stack,見鬼了
07/23 15:39, 1F

07/23 17:23, 9月前 , 2F
你有取消最佳化參數後再去嘗試除錯過嗎?
07/23 17:23, 2F

07/23 22:41, 9月前 , 3F
只錯前四個的話,我感覺比較像gdb抓參數抓錯,自己照calli
07/23 22:41, 3F

07/23 22:42, 9月前 , 4F
ng convention對一下參數值有沒有變
07/23 22:42, 4F

07/23 22:51, 9月前 , 5F
然後沒記錯的話,gdb預設應該是all-stop mode,
07/23 22:51, 5F

07/23 22:51, 9月前 , 6F
所有thread都會停下來才對
07/23 22:51, 6F

07/23 22:54, 9月前 , 7F
真的要抓,如果支援的話可以試試看watchpoints
07/23 22:54, 7F
其實這不是及時gdb的抓取的,這是因為程式crash後,產生了core dump,用gdb去看 的,而程式為什麼crash,最主要原因pu1InOperStatus=0x0 ,因為這是個pointer,而code 對它做指向操作造成segment fault。 只錯前四個是因為我發現到前四個的參數的存放記憶位置是連續,但第5個的記憶體位置 和前4個不是連續的。 目前 其實是這樣認為的 "原本thread 在進入 API,cpu 因context switch 換到其他的thread 而這個thread buff 沒有處理好 Overflow 蓋掉原本thread 的 stack buff" ※ 編輯: tanted (106.1.107.225 臺灣), 07/23/2023 23:40:33

07/24 01:41, 9月前 , 8F
那我覺得最佳化等級的影響可能會更大
07/24 01:41, 8F

07/24 01:41, 9月前 , 9F
或者是上面說的 gdb 沒使用對的呼叫慣例去找參數
07/24 01:41, 9F

07/24 01:43, 9月前 , 10F
每個 thread 會有他自己的 stack, 如果因為堆疊溢位寫到了
07/24 01:43, 10F

07/24 01:43, 9月前 , 11F
其他 thread 的 stack, 那它其實已經蓋掉更多東西了
07/24 01:43, 11F

07/24 01:44, 9月前 , 12F
幾乎不可能到了切過去時才會當掉
07/24 01:44, 12F

07/24 01:44, 9月前 , 13F
(如果真蓋掉更多東西, 很高機會會在蓋掉後不久當掉)
07/24 01:44, 13F

07/24 01:45, 9月前 , 14F
你還是把最佳化選項 (-O3 等) 拔掉後再跑跑看
07/24 01:45, 14F

07/24 09:09, 9月前 , 15F
pthread_attr_setstackaddr 用這個設定不同的 stack addr
07/24 09:09, 15F

07/24 09:09, 9月前 , 16F
看看是不是一樣有這問題
07/24 09:09, 16F
感謝LPH66 給提示的 後來我開始推測可能是進入API後 前面4個變數給記憶體位置可能是不可寫入 也就說從頭到位 變數的值未被修改過 也沒有被其他thread 修改 從一開始進入這個API 就產生segment fault https://upload.cc/i1/2023/07/24/oJ6wfn.jpg
u4IfIndex 的記憶體位置 是 0xaa303f9c 查看 thread map https://upload.cc/i1/2023/07/24/2bNjEW.jpg
https://upload.cc/i1/2023/07/24/Bf2Mkn.jpg
右上圖圈選 得知 0xaa303f9 的確在不可存取記憶空間 目前推測會造成這樣原因 因為我們code 分成三個部分 在build 可能帶的最佳化選項 -O 後面數字都不一樣所造成 ※ 編輯: tanted (106.1.107.225 臺灣), 07/24/2023 21:58:16

07/28 14:29, 9月前 , 17F
用gdb , or gcc 編譯加上-fsanitize=address,or 用
07/28 14:29, 17F

07/28 14:30, 9月前 , 18F
Valgrind等工具探查記憶體
07/28 14:30, 18F

07/28 23:02, 9月前 , 19F
加 compile option 前要先對好環境,不然會很痛苦喔XDD
07/28 23:02, 19F
其實目前這個issue 尚未解掉 但可以避掉 因為那是讓user telnet 進來執行 才creat 出來thread ,如果一次只執行一個thread 就是只讓一個user進來 就不會有這種情形,如果此時再讓第二個user 進來 ,此時creat 出來thread 就會有這種情形。 ※ 編輯: tanted (106.1.107.225 臺灣), 07/29/2023 13:37:44

07/29 17:03, 9月前 , 20F
create
07/29 17:03, 20F

07/29 17:17, 9月前 , 21F
07/29 17:17, 21F

07/29 17:17, 9月前 , 22F
trace 看看
07/29 17:17, 22F
我想目前這跟 gdb 或如何trace無關了 為何local stack variable 會被賦一個"不可存取的記憶位置" 是toolchain 出了問題造成的嗎 toolchain 為 toolchain-arm_cortex-a9+vfpv3-d16_gcc-8.4.0_glibc_eabi 或是編譯時gcc設定參數有關嗎 ※ 編輯: tanted (106.1.107.225 臺灣), 07/29/2023 18:23:17

07/29 18:40, 9月前 , 23F
寫code寫到懷疑toolchain還是gcc有問題的
07/29 18:40, 23F

07/29 18:40, 9月前 , 24F
9成9都是低級bug造成
07/29 18:40, 24F

07/29 19:05, 9月前 , 25F
不能直接watch那個地址嗎
07/29 19:05, 25F

07/29 19:10, 9月前 , 26F
怎麼看你描述只是未初始化變數
07/29 19:10, 26F
這四個變數是API的參數,所以一進去API 他就會被賦予上層傳給他引數值, 所以不可能是未初始化變數,但觀察上層引數卻跟傳下來 前四個參數值不一樣,但後面兩個參數跟上層引數是一樣的。 前四個參數值都變成0,一開始我以為可能被其他thread 類似做memset() 可能使用長度過長導致越界去修改到這個thread 堆疊記憶體導致變成0。 後來經過LPH66 提示,他認為不可能是stackoverflow 造成。 加上我使用GDB trace 使用step 進入這個API 就出現segment fault的訊息出來 讓我開始懷疑可能是被給了不可寫入memory address 我上面貼圖 已經很明顯 看到第一個參數的memory address 是在不可存取區間 而第5個參數是在可寫入memory address,所以他和上層傳來引數是相同 但為什麼會前四個參數的memory address會被賦予在不可存取區間 我目前不得而知 ※ 編輯: tanted (106.1.107.225 臺灣), 07/29/2023 20:29:13

07/29 20:31, 9月前 , 27F
我覺得這個問題沒那麼簡單,看你能不能丟完整 code 出來
07/29 20:31, 27F

07/29 20:32, 9月前 , 28F
不能的話大家只能給你一點想法,剩下的靠通靈
07/29 20:32, 28F

07/29 20:33, 9月前 , 29F
另外這個函數我去查也只有你的文章,不是通用的函式
07/29 20:33, 29F

07/29 20:34, 9月前 , 30F
因為這不是opensource Code 不能隨意放出來
07/29 20:34, 30F

07/29 20:35, 9月前 , 31F
看你的 toolchain 跟 openwrt 應該是在開發嵌入式系統
07/29 20:35, 31F

07/29 20:37, 9月前 , 32F
如果是自己刻的話,有沒有可能是 thread 的實作有問題
07/29 20:37, 32F

07/29 20:37, 9月前 , 33F
,傳 stack 的時候沒對好 ABI?
07/29 20:37, 33F

07/29 20:39, 9月前 , 34F
我個人通靈的話,我會在進去函數的引數的位址設 watch
07/29 20:39, 34F

07/29 20:41, 9月前 , 35F
另外你描述方法讓我聯想到這篇古早的文章:
07/29 20:41, 35F

07/29 20:42, 9月前 , 36F

07/30 12:08, 9月前 , 37F
如果你很確定是multithread在搞何不用 set scheduler-l
07/30 12:08, 37F

07/30 12:08, 9月前 , 38F
ocking on 之類看看不讓thread切換會不會出問題?雖然
07/30 12:08, 38F

07/30 12:08, 9月前 , 39F
不知道用不同優化選項有沒有差但能用sanitizer 或是rr
07/30 12:08, 39F

07/30 12:08, 9月前 , 40F
應該有幫助
07/30 12:08, 40F

07/31 14:17, 9月前 , 41F
如果確定是在 stack 的變數, 那和編譯器無關
07/31 14:17, 41F

07/31 14:18, 9月前 , 42F
這是在程式載入時, sp 被設定了這個位址
07/31 14:18, 42F

07/31 14:19, 9月前 , 43F
gcc 產生的 code 只是在當時 sp 指到的地方存取這些變數
07/31 14:19, 43F

07/31 14:20, 9月前 , 44F
你還是可以試試 pthread_attr_setstackaddr,
07/31 14:20, 44F

07/31 14:21, 9月前 , 45F
把 thread stack 換成 malloc 出來的, 應該就不會在
07/31 14:21, 45F

07/31 14:21, 9月前 , 46F
aa3 開頭的區域, 可能可以避開這問題。
07/31 14:21, 46F
文章代碼(AID): #1alCn-OQ (C_and_CPP)
文章代碼(AID): #1alCn-OQ (C_and_CPP)