作者usanhuang (呱呱)
看板C_and_CPP
标题[问题] 关於副程式呼叫
时间Wed Nov 23 23:28:34 2016
问题(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://webptt.com/cn.aspx?n=bbs/C_and_CPP/M.1479914917.A.5E9.html
1F:→ Schottky: 我的方法是写 Macro 把 __FILE__ 和 __LINE__ 传进来 11/23 23:33
2F:→ Schottky: 再把这两项加入此 function 的 log 印出来就行了 11/23 23:34
3F:推 stupid0319: 用olly吧 11/23 23:40
4F:推 LPH66: 一楼的方法其实就是自动化你所想到的方法 11/23 23:51
5F:→ LPH66: 如果拿不到 stack trace 的话这不失为一个好方法 11/23 23:52
谢谢大家的回应
当时也有想过传__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
6F:推 LPH66: 差不多, 不过函数本身一般参数即可, __FILE__ 用 char* 接 11/24 00:11
7F:→ LPH66: __LINE__ 用 int 接 11/24 00:11
8F:→ LPH66: 函数的参数名自己另外订, 不能直接用 __FILE__ __LINE__ 11/24 00:12
谢谢各位
大致上了解了
但想到一个问题
这样的作法等於是让原本的副程式变为marco
假如有 extern void A ( void*);
这样应该会有问题
但这边应该就无法避掉了吧
只能硬修code了?
※ 编辑: usanhuang (123.192.66.108), 11/24/2016 00:27:29
9F:→ Schottky: extern 一般会集中在 header 吧,只需要改一次 11/24 00:41
10F:→ Schottky: 如果同一个 function 的 extern 散落各处,趁这机会修理 11/24 00:41
11F:→ Schottky: 否则现在不出事,将来若改到 prototype 一样会出事 11/24 00:42
12F:→ firejox: 我习惯会用#直接把macro 转字串 11/24 01:14
13F:推 firejox: 如果有支援c99的话 也可以用__func___ 11/24 01:18
14F:→ uranusjr: 如果是 glibc 的话直接 backtrace() 印出来就好了 11/24 02:21
15F:→ uranusjr: Windows API 似乎也有 stack inspection 但我是没用过 11/24 02:22
16F:推 LPH66: 所以我前面就提了拿不到 stack trace 再说, 不然找那个最快 11/24 02:25
17F:→ stupid0319: 如果在副程式中把ESP存起来呢? 11/24 10:33
18F:→ stupid0319: 这样就知道最後是谁CALL的 11/24 10:33
19F:→ stupid0319: 不是ESP,把call retn的stack返回地址存起来 11/24 10:36
20F:→ LPH66: 这其实就是 stack trace 实际上是怎麽追出来的方法 11/24 17:44
21F:→ LPH66: 配合除错资讯中哪里到哪里是哪个函式就能建构出 trace 了 11/24 17:45
22F:→ LPH66: 但一般程式是不容易抓到这个地方的, 除非对环境很了解 11/24 17:46
23F:→ LPH66: (ie. 能知道要怎麽去找到这个返回地址) 11/24 17:46
24F:→ LPH66: 所以这种东西多半是 runtime 才会/才能提供 11/24 17:47
25F:推 TobyH4cker: VC 的话有这个macro 11/24 22:49
26F:推 flyfoxy: dump file 然後用工具看call stack 11/27 10:37