免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 5078 | 回复: 10
打印 上一主题 下一主题

[C++] 重载全局new,分配类的数组会多8个字节,为什么? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-03-09 18:49 |只看该作者 |倒序浏览
10可用积分
下面这个小程序是重载全局的new/delete操作符来实现对象的分配和释放:
#include <new>
#include <cstdio>
#include <cstdlib>
using namespace std;
void* operator new(size_t size) throw(bad_alloc)
{
printf("operator new:%d Byte\n",size);
void* m=  malloc(size);
if(!m) puts("out of memory");
return m;
}
void operator delete(void* m)throw()
{
puts("operator delete");
free(m);
}
class B
{
int s;
public:
B(){/*puts("B::B()");*/}
~B(){/*puts("B::~B()");*/}
};
int main(int argc, char* argv[])
{
int* p = new int(4);
delete p;
B* s = new B;
delete s;
B* sa = new B[10];
delete []sa;
int* pi=new int[3];
delete []pi;
return 0;
}

程序的输出是
> gcc n.C && ./a.out
operator new:4 Byte
operator delete
operator new:4 Byte
operator delete
operator new:48 Byte         ->问题出在这里,new为类指针数组分配的时候,4x10应该是10个字节,多出来的8个字节是做什么的?
operator new:12 Byte
----------------------------------------------------------------------------------------------------------------
问题: 如上所示, B* sa = new B[10];多出来分配的8个字节,什么作用? 请dx给各解释吧,十分感谢!

最佳答案

查看完整内容

是编译的时候就做到了.如: class B xxxxxxxxxxxxx; p=new B[num];那么编译器会处理成(注意:不同的编译器会有所不同):[ 本帖最后由 system888net 于 2009-3-10 00:42 编辑 ]

论坛徽章:
0
2 [报告]
发表于 2009-03-09 18:49 |只看该作者
原帖由 jeanlove 于 2009-3-9 22:37 发表
1. 多了8个字节可能是因为我开始是在solaris位CC上面编译的。我在另一个机器32bit Linux上面gcc的结果就是多了4个字节。

2. 这个class改为struct,结果不变,去掉了重载的Operator delete结果也不变。但是如 ...


是编译的时候就做到了.

如:
    class B xxxxxxxxxxxxx;
    p=new B[num];
那么编译器会处理成(注意:不同的编译器会有所不同):

  1.   +--------------------------------------------------------------+
  2.    |num|var[0]|var[1]|var[2]|var[3]|........|var[num-1]|
  3.   +--------------------------------------------------------------+

  4.         push        n               ;n=num*var_size+4
  5.         call           你重载的new       
  6.         ....................................
  7.         push        B::~B()的地址
  8.         push        B::B()的地址
  9.         *((int*)p)=num;
  10.         ((int*)p)++;
  11.         push        num
  12.         push        var_size     
  13.         push    p
  14.         call          vector_constructor_iterator  ;这里会循环调用B::B(),次数是num
复制代码

[ 本帖最后由 system888net 于 2009-3-10 00:42 编辑 ]

论坛徽章:
0
3 [报告]
发表于 2009-03-09 19:30 |只看该作者
很奇怪,可能跟数组大小的记录有关(但我觉得不应该体现在传入的size参数中),关注

评分

参与人数 1可用积分 +1 收起 理由
jeanlove + 1 我很赞同

查看全部评分

论坛徽章:
0
4 [报告]
发表于 2009-03-09 20:50 |只看该作者
原帖由 jeanlove 于 2009-3-9 18:49 发表
下面这个小程序是重载全局的new/delete操作符来实现对象的分配和释放:
#include
#include
#include
using namespace std;
void* operator new(size_t size) throw(bad_alloc)
{
printf("operator ne ...


是40就奇怪了!
这是取决编译器实现的相关问题.

对于LZ的这种特定写法:

对于class B 不同于int

对于new B,      一般是4
对于new B[1],  一般不会是4
对于new B[2],  不可能是8
对于new B[3],  不可能是12
......
对于new B[10], 不可能是40

多出来的也不一定是8,这取决于不同的编译器实现(比如有的编译器可能是多4).

建议了解一下编译器具体实现!

论坛徽章:
0
5 [报告]
发表于 2009-03-09 22:37 |只看该作者

补充一下:

1. 多了8个字节可能是因为我开始是在solaris位CC上面编译的。我在另一个机器32bit Linux上面gcc的结果就是多了4个字节。

2. 这个class改为struct,结果不变,去掉了重载的Operator delete结果也不变。但是如果去掉了显示的析构函数~B(),不管我有没有重载delete,就都不会产生多处的字节。

问题确实存在: 为什么传入的size_t变量增加了呢? 是编译时做到的? 运行时做到的?

论坛徽章:
0
6 [报告]
发表于 2009-03-09 23:54 |只看该作者

回复 #4 jeanlove 的帖子

可能是这样的(猜的):
对类类型,delete一个数组时(比如,delete []sa;),要为每一个数组元素调用析构函数。但对于delete表达式(比如,这里的delete []sa),它并不知道数组的元素个数(只有new函数和delete函数知道)。因此,必须有一种手段来告诉delete表达式的数组大小是多少。那么一种可行的方式就是,多分配一个大小为4字节的空间来记录数组大小,并可以约定前四字节来记录大小。那么,由new函数分配的地址与new表达式返回的地址应该相差4个字节(这可以写程序来验证)。对于非类类型数组和不需要调用析构函数的类类型数组,这多于的四字节就不需要了。

评分

参与人数 1可用积分 +2 收起 理由
jeanlove + 2 我很赞同

查看全部评分

论坛徽章:
0
7 [报告]
发表于 2009-03-09 23:55 |只看该作者
mark 为什么参数会变是重点

论坛徽章:
0
8 [报告]
发表于 2009-03-10 00:19 |只看该作者

回复 #7 system888net 的帖子

因为类的实例数组需要调用vector_constructor_iterator来循环初试化各个单元(当然用的是B::B()....).
因此跟类的单个实例处理方式不一样,前面留出了4byte(或说是若干byte)记录有数组多少个事例的.

论坛徽章:
0
9 [报告]
发表于 2009-03-10 00:39 |只看该作者
原帖由 tyc611 于 2009-3-9 23:54 发表
可能是这样的(猜的):
对类类型,delete一个数组时(比如,delete []sa,要为每一个数组元素调用析构函数。但对于delete表达式(比如,这里的delete []sa),它并不知道数组的元素个数(只有new函数和dele ...


赞一个.

论坛徽章:
0
10 [报告]
发表于 2009-03-10 09:40 |只看该作者
原帖由 system888net 于 2009-3-10 00:12 发表


是编译的时候就做到了.

如:
    class B xxxxxxxxxxxxx;
    p=new B[num];
那么编译器会处理成(注意:不同的编译器会有所不同):

  +----------------------------------------------------------- ...

嗯,感觉这个解释很强大,能解决我的问题
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP