注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

Code@Pig Home

喜欢背着一袋Code傻笑的Pig .. 忧美.欢笑.记忆.忘却 .之. 角落

 
 
 

日志

 
 

new [] / delete [] 之细节  

2012-09-23 21:01:48|  分类: lang_c/c++ |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
wellbye 在csdn上发现的一个有趣问题。果然很坑人,mark之。

#include <iostream>

using namespace std;
class Base
{
public:
  Base(){}
  virtual ~Base(){}
};

class Derived :public Base
{
private:
  int i;
public:
  Derived(): i(10) {}
  virtual ~Derived() {}
};
int main()
{
  Base *p = new Derived[2];
  delete [] p;
  return 0;
}


#4楼:
个人认为这可能是implementation相关的。
编译器可能使用p指向的内存块的大小/要删除的指针的静态类型的大小来获取p指向的Base对象的个数。

int c = sizeof(Derived[2]) / sizeof(Base); // may larger than 2
for (i = 0 to c)
  destructor_Base( p + sizeof(Base) * i ); // may not point to a valid Derived
free (p);

#5楼:
虽然一看大致知道了原因,但还是饶有兴致的拿gcc -S生成汇编验证了下:

delete [] p; 这一句对应的大致是:
    
L21:
  cmpl 28(%esp), %ebx
  je L20
  subl $4, %ebx
  movl (%ebx), %eax
  movl (%eax), %eax
  movl %ebx, (%esp)
  call *%eax
  jmp L21
L20:

很明显这里在对数组p中的元素做循环析构,但是每次循环,对象地址减少的却是4:
subl $4, %ebx
也就是说它认为p中的元素都是一连串Base对象,其大小为4(一个虚表指针的开销)。
而实际上p中元素是大小为8的Derived对象。
把p声明成Derived*后,上面的subl $4就变成$8了。

这确实是个少见的误区,一般以为只要基类析构声明为虚就万事大吉了
但是new[]和delete[]真的是个陷井遍布的怪胎,建议没事就不要用它们了,自己手动分配也不过多几行代码。
  评论这张
 
阅读(643)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017