[BUG]memset引起的虚表异常

先上代码和结论:
class A{...................};
int main()
     A* pA = malloc(sizeof(A));
     memset(pA,0,sizeof(A));
     ............
     printf("hello world!");
}
大致伪代码可以这么写了。
这里看,就是使用了C的内存申请方式来初始化了一个C++的类A的实例。这样的做法,现在可能不常见,但是在比较老旧的框架或者代码中依然存在。然后笔者经历了一个因为这种方式导致的诡异bug。

我们先讨论一下,照C++的模式来思考,这里可能存在的问题。

1,首先看sizeof(A)是否可能为0?
     不可能,因为C++标准制定了,当A即使没有任何成员变量时,sizeof(A)==1。否则sizeof(A)==0的话会导致无成员变量的类无法申请内存(因为成员函数不占内存,至于成员函数和成员变量占据内存的差异,这里简单说就是,成员函数不占据任何类成员空间,因为他们所处的域不同,成员函数处于代码段,而成员变量一般处于堆栈数据段)。所以即使是一个有1000个成员方法没有任何成员变量的类,他的size依然是1。

2,照1的结论来看,假设对于类,仅有类成员变量占据空间的情况下,这里应该是不存在问题的。代码与数据分离,数据又被格式化为0。看上去很ok。但是实际上C++还有另外一种占据类内存空间的对象,举个例,比如虚表指针。

虚表:
https://www.cnblogs.com/hushpa/p/5707475.html
https://www.cnblogs.com/vipchenwei/p/7466018.html?utm_source=debugrun&utm_medium=referral
https://blog.csdn.net/u014744118/article/details/51020480(这个不知道被面试题考过多少次,现在还在考)
这三篇文章看完看懂的话,就会理解上面这个代码在某些情况下,就会出现问题。

在类存在虚函数的情况下,类会有一张虚表(除非你ATL_NO_VTABLE,)这样,在C的初始化模式下,会将虚表的头指针指向0地址,这样就会造成非法指针访问。因为虚函数是根据虚表头进行索引找到虚函数入口地址,一旦虚表头置0,那就是0是第一个虚函数入口地址,发生虚函数访问或者多态,立马崩。

笔者在对应的出错地看到了一个 : 有效指针->有效方法的访问模式,然后经过debug调试查找找到这个bug,中间涉及C++的内存模型,还有C++初始化和C模式的malloc初始化方式的区别,除了new之外,虚表还有其他很多因素都是malloc无法替代的。

Warning!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值