[問題] 關於副程式呼叫

看板C_and_CPP (C/C++)作者 (呱呱)時間9年前 (2016/11/23 23:28), 9年前編輯推噓7(7019)
留言26則, 7人參與, 最新討論串1/1
問題(Question): 在大型系統遇到了一些問題 有一個副程式A裡面做的事情是free動態記憶體 它的code就是傳入記憶體再把它free掉 所以很多function都有用到他 但有某個function寫錯了呼叫了A free了不該free的記憶體 有方法可以知道是哪個function呼叫了A嗎? 因為印出的log只有顯示死在A 很多function都沒加log, 因此完全看不到東西 但關鍵應該是呼叫的那個function傳的記憶體位置 老實說只想到在每個function呼叫A前都加個printf看看兇手是誰 但這樣有點像土法煉鋼 想知道有沒有更聰明的方法知道是哪個function呼叫的 感覺上應該是有方法的 謝謝大家 -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 123.192.66.108 ※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1479914917.A.5E9.html

11/23 23:33, , 1F
我的方法是寫 Macro 把 __FILE__ 和 __LINE__ 傳進來
11/23 23:33, 1F

11/23 23:34, , 2F
再把這兩項加入此 function 的 log 印出來就行了
11/23 23:34, 2F

11/23 23:40, , 3F
用olly吧
11/23 23:40, 3F

11/23 23:51, , 4F
一樓的方法其實就是自動化你所想到的方法
11/23 23:51, 4F

11/23 23:52, , 5F
如果拿不到 stack trace 的話這不失為一個好方法
11/23 23:52, 5F
謝謝大家的回應 當時也有想過傳__FILE__ 和 __LINE__ 但讓 A 多傳兩個參數, 感覺每個呼叫的A都要修改 這樣跟前面都加printf好像差不多 而Schottky 意思是像這樣嗎? // 宣告一個macro 名稱為functionA #define A(ptr) A2(ptr, __FILE__, __LINE__) // 原function本體A修改名稱為A2並多傳兩個string void A2 ( ptr, __FILE__, __LINE__ ) { printf ( __FILE__, __LINE__ ); } 不知道有沒有誤會 ※ 編輯: usanhuang (123.192.66.108), 11/24/2016 00:05:55

11/24 00:11, , 6F
差不多, 不過函數本身一般參數即可, __FILE__ 用 char* 接
11/24 00:11, 6F

11/24 00:11, , 7F
__LINE__ 用 int 接
11/24 00:11, 7F

11/24 00:12, , 8F
函數的參數名自己另外訂, 不能直接用 __FILE__ __LINE__
11/24 00:12, 8F
謝謝各位 大致上了解了 但想到一個問題 這樣的作法等於是讓原本的副程式變為marco 假如有 extern void A ( void*); 這樣應該會有問題 但這邊應該就無法避掉了吧 只能硬修code了? ※ 編輯: usanhuang (123.192.66.108), 11/24/2016 00:27:29

11/24 00:41, , 9F
extern 一般會集中在 header 吧,只需要改一次
11/24 00:41, 9F

11/24 00:41, , 10F
如果同一個 function 的 extern 散落各處,趁這機會修理
11/24 00:41, 10F

11/24 00:42, , 11F
否則現在不出事,將來若改到 prototype 一樣會出事
11/24 00:42, 11F

11/24 01:14, , 12F
我習慣會用#直接把macro 轉字串
11/24 01:14, 12F

11/24 01:18, , 13F
如果有支援c99的話 也可以用__func___
11/24 01:18, 13F

11/24 02:21, , 14F
如果是 glibc 的話直接 backtrace() 印出來就好了
11/24 02:21, 14F

11/24 02:22, , 15F
Windows API 似乎也有 stack inspection 但我是沒用過
11/24 02:22, 15F

11/24 02:25, , 16F
所以我前面就提了拿不到 stack trace 再說, 不然找那個最快
11/24 02:25, 16F

11/24 10:33, , 17F
如果在副程式中把ESP存起來呢?
11/24 10:33, 17F

11/24 10:33, , 18F
這樣就知道最後是誰CALL的
11/24 10:33, 18F

11/24 10:36, , 19F
不是ESP,把call retn的stack返回地址存起來
11/24 10:36, 19F

11/24 17:44, , 20F
這其實就是 stack trace 實際上是怎麼追出來的方法
11/24 17:44, 20F

11/24 17:45, , 21F
配合除錯資訊中哪裡到哪裡是哪個函式就能建構出 trace 了
11/24 17:45, 21F

11/24 17:46, , 22F
但一般程式是不容易抓到這個地方的, 除非對環境很了解
11/24 17:46, 22F

11/24 17:46, , 23F
(ie. 能知道要怎麼去找到這個返回地址)
11/24 17:46, 23F

11/24 17:47, , 24F
所以這種東西多半是 runtime 才會/才能提供
11/24 17:47, 24F

11/24 22:49, , 25F
VC 的話有這個macro
11/24 22:49, 25F

11/27 10:37, , 26F
dump file 然後用工具看call stack
11/27 10:37, 26F
文章代碼(AID): #1ODRMbNf (C_and_CPP)
文章代碼(AID): #1ODRMbNf (C_and_CPP)