头文件和.a(库文件不匹配)导致虚函数错位,进而导致的bug
来源:互联网 发布:01年总决赛艾弗森数据 编辑:程序博客网 时间:2024/03/29 19:10
头文件和.a(库文件不匹配)导致虚函数错位,进而导致的bug
该bug的快速定位技巧
bt查看函数调用堆栈. 如果堆栈的顺序错乱, 则可能是虚函数表错乱导致.
本例中, GetTPLContent 的上层很明显不应该是 DealInput, 因为DealInput没有调用GetTPLContent
故障回顾:
某日遇到一个奇葩bug, 进程core, 查看堆栈, core的位置没有任何异常, 在一个不可能出问题的地方出错了. 只根据core文件在生产环境无法排查.
在开发机生把cgi编译成可执行文件, 用gdb跟踪, 发现在 单步跟进 BeforeProcess() 函数时, 却意外的跳到了 GetTPLContent()函数接下来就是core了.
中断现场如下:
rogram received signal SIGSEGV, Segmentation fault.
[Switching to Thread -1211028832 (LWP 10060)]
0xb7ef2422 in std::string::compare () from /usr/lib/libstdc++.so.6
(gdb) bt
#0 0xb7ef2422 in std::string::compare () from /usr/lib/libstdc++.so.6
#1 0x08055e5c in std::operator==<char, std::char_traits<char>, std::allocator<char> > (__lhs=@0xbfcd60ec, __rhs=0x82a080e "json")
at /usr/include/c++/4.1.0/bits/basic_string.h:2163
#2 0x0804eea0 in CMyCGI::GetTPLContent (this=0xbfcd505c) at src/mb_get_app_friends.cpp:165
#3 0x08260eb0 in COpenAPIBase::DealInput (this=0xbfcd4128, params=@0xbfcd505c) at src/openapi_base.cpp:239
#4 0x0821b9af in CCGIEx::Run (this=0xbfcd4128, pszTemplateFile=0x0) at cgiex.cpp:248
#5 0x08051205 in main () at src/mb_get_app_friends.cpp:386
把栈帧定位到COpenAPIBase::DealInput上
(gdb) frame 3
#3 0x08260eb0 in COpenAPIBase::DealInput (this=0xbfcd4128, params=@0xbfcd505c) at src/openapi_base.cpp:239
239 BeforeProcess(params);
(gdb) l
234 //把参数转化成值
235 TransParams(params);
236 //填充出authinfo
237 FillOpenAPIInfo();
238
239 BeforeProcess(params);
240 m_mod_ret = Process(params);
241 AfterProcess(params);
242 return true;
243 }
查看汇编
(gdb) disassemble
Dump of assembler code for function _ZN12COpenAPIBase9DealInputERSt3mapISsSsSt4lessISsESaISt4pairIKSsSsEEE:
0x08260e76 <_ZN12COpenAPIBase9DealInputERSt3mapISsSsSt4lessISsESaISt4pairIKSsSsEEE+0>: push %ebp
0x08260e77 <_ZN12COpenAPIBase9DealInputERSt3mapISsSsSt4lessISsESaISt4pairIKSsSsEEE+1>: mov %esp,%ebp
0x08260e79 <_ZN12COpenAPIBase9DealInputERSt3mapISsSsSt4lessISsESaISt4pairIKSsSsEEE+3>: push %esi
0x08260e7a <_ZN12COpenAPIBase9DealInputERSt3mapISsSsSt4lessISsESaISt4pairIKSsSsEEE+4>: push %ebx
0x08260e7b <_ZN12COpenAPIBase9DealInputERSt3mapISsSsSt4lessISsESaISt4pairIKSsSsEEE+5>: sub $0x10,%esp
0x08260e7e <_ZN12COpenAPIBase9DealInputERSt3mapISsSsSt4lessISsESaISt4pairIKSsSsEEE+8>: mov 0x8(%ebp),%ebx
0x08260e81 <_ZN12COpenAPIBase9DealInputERSt3mapISsSsSt4lessISsESaISt4pairIKSsSsEEE+11>: mov 0xc(%ebp),%esi
0x08260e84 <_ZN12COpenAPIBase9DealInputERSt3mapISsSsSt4lessISsESaISt4pairIKSsSsEEE+14>: mov (%ebx),%eax
0x08260e86 <_ZN12COpenAPIBase9DealInputERSt3mapISsSsSt4lessISsESaISt4pairIKSsSsEEE+16>: mov %esi,0x4(%esp)
0x08260e8a <_ZN12COpenAPIBase9DealInputERSt3mapISsSsSt4lessISsESaISt4pairIKSsSsEEE+20>: mov %ebx,(%esp)
0x08260e8d <_ZN12COpenAPIBase9DealInputERSt3mapISsSsSt4lessISsESaISt4pairIKSsSsEEE+23>: call *0x10(%eax) // 虚函数 GetDftParams
0x08260e90 <_ZN12COpenAPIBase9DealInputERSt3mapISsSsSt4lessISsESaISt4pairIKSsSsEEE+26>: mov %esi,0x4(%esp)
0x08260e94 <_ZN12COpenAPIBase9DealInputERSt3mapISsSsSt4lessISsESaISt4pairIKSsSsEEE+30>: mov %ebx,(%esp)
0x08260e97 <_ZN12COpenAPIBase9DealInputERSt3mapISsSsSt4lessISsESaISt4pairIKSsSsEEE+33>: call 0x8260684 <_ZN12COpenAPIBase11TransParamsERSt3mapISsSsSt4lessISsESaISt4pairIKSsSsEEE>
0x08260e9c <_ZN12COpenAPIBase9DealInputERSt3mapISsSsSt4lessISsESaISt4pairIKSsSsEEE+38>: mov %ebx,(%esp)
0x08260e9f <_ZN12COpenAPIBase9DealInputERSt3mapISsSsSt4lessISsESaISt4pairIKSsSsEEE+41>: call 0x825fbcc <_ZN12COpenAPIBase15FillOpenAPIInfoEv>
0x08260ea4 <_ZN12COpenAPIBase9DealInputERSt3mapISsSsSt4lessISsESaISt4pairIKSsSsEEE+46>: mov (%ebx),%eax
0x08260ea6 <_ZN12COpenAPIBase9DealInputERSt3mapISsSsSt4lessISsESaISt4pairIKSsSsEEE+48>: mov %esi,0x4(%esp)
0x08260eaa <_ZN12COpenAPIBase9DealInputERSt3mapISsSsSt4lessISsESaISt4pairIKSsSsEEE+52>: mov %ebx,(%esp)
0x08260ead <_ZN12COpenAPIBase9DealInputERSt3mapISsSsSt4lessISsESaISt4pairIKSsSsEEE+55>: call *0x18(%eax) // 虚函数 BeforeProcess
0x08260eb0 <_ZN12COpenAPIBase9DealInputERSt3mapISsSsSt4lessISsESaISt4pairIKSsSsEEE+58>: mov (%ebx),%eax
0x08260eb2 <_ZN12COpenAPIBase9DealInputERSt3mapISsSsSt4lessISsESaISt4pairIKSsSsEEE+60>: mov %esi,0x4(%esp)
0x08260eb6 <_ZN12COpenAPIBase9DealInputERSt3mapISsSsSt4lessISsESaISt4pairIKSsSsEEE+64>: mov %ebx,(%esp)
0x08260eb9 <_ZN12COpenAPIBase9DealInputERSt3mapISsSsSt4lessISsESaISt4pairIKSsSsEEE+67>: call *0x20(%eax) // 虚函数 Process
0x08260ebc <_ZN12COpenAPIBase9DealInputERSt3mapISsSsSt4lessISsESaISt4pairIKSsSsEEE+70>: mov %eax,0xf94(%ebx)
0x08260ec2 <_ZN12COpenAPIBase9DealInputERSt3mapISsSsSt4lessISsESaISt4pairIKSsSsEEE+76>: mov (%ebx),%eax
0x08260ec4 <_ZN12COpenAPIBase9DealInputERSt3mapISsSsSt4lessISsESaISt4pairIKSsSsEEE+78>: mov %esi,0x4(%esp)
0x08260ec8 <_ZN12COpenAPIBase9DealInputERSt3mapISsSsSt4lessISsESaISt4pairIKSsSsEEE+82>: mov %ebx,(%esp)
0x08260ecb <_ZN12COpenAPIBase9DealInputERSt3mapISsSsSt4lessISsESaISt4pairIKSsSsEEE+85>: call *0x1c(%eax) // 虚函数 AfterProcess
0x08260ece <_ZN12COpenAPIBase9DealInputERSt3mapISsSsSt4lessISsESaISt4pairIKSsSsEEE+88>: mov $0x1,%eax
0x08260ed3 <_ZN12COpenAPIBase9DealInputERSt3mapISsSsSt4lessISsESaISt4pairIKSsSsEEE+93>: add $0x10,%esp
0x08260ed6 <_ZN12COpenAPIBase9DealInputERSt3mapISsSsSt4lessISsESaISt4pairIKSsSsEEE+96>: pop %ebx
0x08260ed7 <_ZN12COpenAPIBase9DealInputERSt3mapISsSsSt4lessISsESaISt4pairIKSsSsEEE+97>: pop %esi
0x08260ed8 <_ZN12COpenAPIBase9DealInputERSt3mapISsSsSt4lessISsESaISt4pairIKSsSsEEE+98>: pop %ebp
0x08260ed9 <_ZN12COpenAPIBase9DealInputERSt3mapISsSsSt4lessISsESaISt4pairIKSsSsEEE+99>: ret
这个时候, 如果嗅觉敏锐就已经可以看到问题了, TransParams 在头文件里是个虚函数, 理论上是无法在反汇编里直接看到函数符号的 (因为虚函数的具体的地址, 只有在运行时才能决定)
进一步验证
单步执行时, 当执行到BeforeProcess时, s跳进去, 代码却跳到 GetTPLContent, 因此严重怀疑是 我使用的头文件 和 .a库不匹配导致.
头文件更新了, .a库却没有更新, 如果头文件中新增虚函数, 将导致虚函数表中各个虚函数的位置发生改变, 而.a却使用旧的虚函数表!
重新编译.a库后bug消失.
这个bug让我想起了以前在windows环境下遭遇的著名的"dll地狱"bug, 都是由于虚函数表错位导致的.
- 头文件和.a(库文件不匹配)导致虚函数错位,进而导致的bug
- 头文件不匹配导致的崩溃问题
- openssl 头文件和库文件版本不一致导致crash
- 头文件和Dll不一致导致的问题
- 头文件相互包含导致的错误
- 缺少头文件导致的段错误
- 服务器掉电导致控制文件与数据文件不匹配
- use_concat导致not in时临时表不动态采样进而导致的性能问题
- 动态库的头文件和 .lib 文件不匹配引发的问题
- linux和window下socket接口函数的传入参数不匹配,导致出错。
- stdafx.h 包含的头文件出错,导致大问题.
- 头文件的相互包含会导致错误
- linux tcp 编程中头文件引用导致的惨案
- 头文件相互包含导致的错误 解决
- 头文件的相互包含会导致错误
- php fwrite写入文件bom头导致的乱码问题解决
- 浅谈自定义头文件可能导致的重定义问题
- FreeMarker的FTL页面中include引用UTF-8文件导致错位的问题处理
- IAP LPC 8000
- 标准库循环队列应用
- 2013年3月15日 工作总结
- io流 1
- 类成员函数的地址
- 头文件和.a(库文件不匹配)导致虚函数错位,进而导致的bug
- 2013年03月18日 工作总结
- 用Raspberry Pi和乐高打造廉价超级计算机
- 最近一周生日提醒
- 笔记本是window 7 x86 旗舰版sp1无线上网的,虚拟机是桥接模式,怎么相互ping通呢
- Bibliography in optical music recognition
- Android2.3 中如何使用GPU硬件加速
- 热门手机应用界面分析--微信欢迎页面
- 黑莓CEO海因斯对iPhone的评价是用户界面已5年没创新了