请问关于 new(p) T[n]的用法

mathe 2009-03-11 09:31:43
最近我在程序里面发现一个BUG,是由于在代码中使用了下面的方法

T *p=(T *)malloc(sizeof(T)*n);
p=new(p) T[n];

后来发现程序发生内存溢出问题。
用VC跟踪汇编发现对于代码
p=new(p) T[n];
VC在产生上面的代码时,会使用指针p指向的最前面4个字节来保存元素数目(就是n),所以实际上需要的内存至少是sizeof(T)*n+sizeof(int)(但是由于对齐问题,可能需要更大的空间).
请问各位C++大牛,C++规范里面有没有对new(p) T[n]这样语法的相关的规定?
...全文
535 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
mathe 2009-03-13
  • 打赏
  • 举报
回复
只好通过使用循环
for(int i=0;i<n;i++)new (p+i) T;
来解决这个问题了
yshuise 2009-03-13
  • 打赏
  • 举报
回复
唉!本来不想说的。但是。。。
一楼明显是错的嘛!楼主不要坚持自己的想法了,多看点书吧。
liuysheng 2009-03-11
  • 打赏
  • 举报
回复
以前好像没见到过...
学习
chenyingshu 2009-03-11
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 yshuise 的回复:]
引用 11 楼 mathe 的回复:
不是内存泄漏,而是内存溢出。
8楼的可以printf("%d\n",(int)iPtr-ptr)
看看
有内存溢出不一定就必然能看到。

至于10楼的代码,正好没有内存溢出,不过不出问题只是运气好,可以改成
C/C++ code#include"stdafx.h"staticintc=0;classT{public:
T(){x=c++;}intgetX()const{returnx;}private:intx;
};int_tmain(intargc, _TCHAR*argv[])
{
T*p=(T*)malloc(sizeof(T)*1000);…
[/Quote]
我也试过了,可以的。
就呆在云上 2009-03-11
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 taodm 的回复:]
其实,可以直接把项目组里使用placement new的人叉出去打50大板。
这是一个应该严格禁用的语法。
[/Quote]

呵呵
stl里面就非常多placement new,就是alloc里面的construct函数吧
虽然我没有在实际项目里面用过,但是我觉得应该可以的
beijingzb 2009-03-11
  • 打赏
  • 举报
回复
new和malloc一起用的话就很麻烦,最安全的做法还是malloc和free一起用,new和delete一起用。自己管理内存其实就是自己模仿编译器实现operator new,所以一定要对编译器的细节很了解才可以。要不是逼得没办法,完全没必要这么用,这就是隐患哪。
mathe 2009-03-11
  • 打赏
  • 举报
回复
我也测试了一下,发现重新模拟的各种代码的确都不会加4(就除了我程序中的代码),所以看来1楼的解释也不精确。
我甚至另外写好一个类,其中数据成员排序都相同,而且使用同样继承关系,同样基类定义了虚函数。
最后除了类名和成员函数不同外,几乎结构都相同,而且将代码嵌入到同一个工程中。可是就是没有那个加4的问题。
感觉像是编译器有些问题
yshuise 2009-03-11
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 mathe 的回复:]
不是内存泄漏,而是内存溢出。
8楼的可以printf("%d\n",(int)iPtr-ptr)
看看
有内存溢出不一定就必然能看到。

至于10楼的代码,正好没有内存溢出,不过不出问题只是运气好,可以改成
C/C++ code#include"stdafx.h"staticintc=0;classT{public:
T(){x=c++;}intgetX()const{returnx;}private:intx;
};int_tmain(intargc, _TCHAR*argv[])
{
T*p=(T*)malloc(sizeof(T)*1000);new(p)T[1000];for(inti=0; i<1000; i++)…
[/Quote]
我调试了一下输出正确。最后发现原因可能是屏幕不够的问题。只需要把
 printf("%d\n",p[i].getX());

改成:
printf("%d ",p[i].getX());

就可以全部正确看到内容。
beyond071 2009-03-11
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 mathe 的回复:]
不是内存泄漏,而是内存溢出。
8楼的可以printf("%d\n",(int)iPtr-ptr)
看看
有内存溢出不一定就必然能看到。

至于10楼的代码,正好没有内存溢出,不过不出问题只是运气好,可以改成

C/C++ code
#include "stdafx.h"
static int c=0;
class T{
public:
T(){x=c++;}
int getX()const{return x;}
private:
int x;
};
int _tmain(int argc, _TCHAR* argv[])
{
T* p = (T*)malloc(sizeof…
[/Quote]


void *ptr = operator new(sizeof(int)*100);

int *iPtr = new(ptr)int[100];//

for (int i = 0; i < 100; i++)
{
iPtr[i] = i;
}

cout << (int)(iPtr-(int*)ptr) << endl;

operator delete (ptr);


iPtr - ptr的结果是0
taodm 2009-03-11
  • 打赏
  • 举报
回复
其实,可以直接把项目组里使用placement new的人叉出去打50大板。
这是一个应该严格禁用的语法。
mathe 2009-03-11
  • 打赏
  • 举报
回复
不是内存泄漏,而是内存溢出。
8楼的可以printf("%d\n",(int)iPtr-ptr)
看看
有内存溢出不一定就必然能看到。

至于10楼的代码,正好没有内存溢出,不过不出问题只是运气好,可以改成

#include "stdafx.h"
static int c=0;
class T{
public:
T(){x=c++;}
int getX()const{return x;}
private:
int x;
};
int _tmain(int argc, _TCHAR* argv[])
{
T* p = (T*)malloc(sizeof(T)*1000);
new(p)T[1000];
for (int i = 0; i < 1000; i++)
{
printf("%d\n",p[i].getX());
}
free(p);
return 0;
}

然后看看结果是否正确
beyond071 2009-03-11
  • 打赏
  • 举报
回复
malloc分配的用free释放 operator new分配的用operator delete释放,差不多就这样了...
yshuise 2009-03-11
  • 打赏
  • 举报
回复
我用boundschecker测试了一下,无内存泄漏:
#include "stdafx.h"
class T{
public:
~T(){}
private:
int x;
};
int _tmain(int argc, _TCHAR* argv[])
{
T* p = (T*)malloc(sizeof(T)*1000);
new(p)T[1000];
for (int i = 0; i < 1000; i++)
{
p[i].~T();
}
free(p);
return 0;
}

beyond071 2009-03-11
  • 打赏
  • 举报
回复

void *ptr = operator new(sizeof(int)*100);

int *iPtr = new(ptr)int[100];//

for (int i = 0; i < 100; i++)
{
iPtr[i] = i;
}

operator delete (ptr);

这样也没问题啊
mathe 2009-03-11
  • 打赏
  • 举报
回复
6楼的方法也有问题的,虽然你的第一个operator new也多分配了一个sizeof(int)的内存。
当然你这个测试的方法可能有问题,如果你没有真正向内存写数据,自然看不出内存泄漏。

我上面用的malloc只是一个例子,实际上我的代码中是需要要自定义的函数(内存池)来管理内存。
beyond071 2009-03-11
  • 打赏
  • 举报
回复
void *ptr = operator new(sizeof(int)*100);

int *iPtr = new(ptr)int[100];//

operator delete (ptr);

我试了下也没出问题哈
yshuise 2009-03-11
  • 打赏
  • 举报
回复
stl 的 allocate实际上是调用malloc来实现的。
  • 打赏
  • 举报
回复
定位new最好跟allocate一起用吧,跟malloc,总感觉怪怪的。
yshuise 2009-03-11
  • 打赏
  • 举报
回复
我觉得不会出问题。
malloc会自动的内存对齐,或是cookies,
而定位new只是在内存上构造对象。
楼主代码内存泄漏才是真的。
mathe 2009-03-11
  • 打赏
  • 举报
回复
应该是只有new []才需要额外的内存。而且保存的好像是元素数目而不是内存大小。
这个实在有点过于麻烦了,偏偏我这里T是一个模板类,考虑到对象起始地址还可能8个字节对齐,简单加sizeof(int)是不行的
加载更多回复(1)

64,647

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧