今天在集成程序时,一个同事调试他那部分时出了一个诡诈的问题,delete一个堆变量时程序crash掉。开始以为某个没有重新编译的问题(因为以前遇到过诡诈的问题,是没有重新编译,编译器的bug导致),结果不是,#prama pack(push/pop)没有配对(也遇到过没配对出现不可预期的问题)。都不是。
开始在delete处反汇编调试,发现EAX寄存器(应该是析构函数首地址)变成0.导致程序crash掉。挺怪异。仔细研究了一下此结构体,发现有虚指针。且虚指针为0.这就是程序死掉的原因。为什么为0?还以为其他地方给修改了。(发现在结构体刚New完,虚指针就为空)。找到结构体定义处,发现问题所在。
以下为定义示例:
struct AA
{
...
}
struct BB
{
struct AA* m_pAA;
....
BB()
{
memset(this,0,sizeof(struct BB) ); //问题所在,以前还没见过这么用的,导致虚指针为空,
//如果没有虚指针这么用没有什么问题。
}
virtual ~BB() //问题所在
{
if( m_pAA != NULL)
{
delete m_pAA;
m_pAA = NULL;
}
}
}
总结两条结论:
(1): 结构体构造函数不要对this指针直接操作(不小心会出现不可预期的问题),仅对其成员变量进行初始化就可以了。
(2):结构体不需要继承,没有必要用虚函数,这会增大结构体体积(虚指针会占4个字节)。如果有虚函数,直接用类好了。