我有这段代码
int main()
{
int *b = new int(8);
cout<<" &b = "<<b<<endl;
delete b;
void *place = (void*)0x3c0fa8; //in my output i am getting this value in &b
int *i = new(place) int(8);
system("PAUSE");
return 0;
}
我怀疑是我为“b”分配空间,并将其删除,现在如果我分配另一个整数空间,它就会出现与先前分配的位置相同,现在如果我强制将整数值放到此值(删除后),我收到了SEGFAULT。
此代码有什么问题?
感谢。
答案 0 :(得分:3)
不能保证每次b
都会被分配到同一个内存位置,事实上它并不常见,你不应该依赖它。
对于这种情况,place
实际上指向了无效的地址,访问它会导致Segfault。
即使place
指向分配了b
的同一位置,在删除b
后,内存也会被取消分配,并且不属于您的程序。在int *i = new(place) int(8);
执行之前,该内存位置可能已由任何其他进程分配。因此,再次访问它将导致Segfault。
答案 1 :(得分:1)
使用从堆中分配 的内存,之后它已被释放(使用delete
)是未定义的行为。据我们所知,堆的那个单元可能已经完全释放回操作系统[因此在您的进程中不再可用作内存](事实上,Windows几乎直接调用操作系统进行所有堆分配,并且它有可能它释放堆所在的整个内存块)。
然而,第二个new
调用更有可能成功,而你只是覆盖了属于堆的一些堆内存,所以当代码试图退出时(并且免费)在main
之前分配的一些东西,它会失败。
如果你要这样做
int main()
{
int *b = new int(8);
cout<<" &b = "<<b<<endl;
// delete b;
int *i = new(b) int(8);
}
它很有可能工作,因为你已经释放后不再使用堆内存。 (当然,您可能希望将第二个8更改为9或其他内容以查看差异......;)
答案 2 :(得分:0)
看起来您使用展示位置new
错误了。展示位置new
运算符用于在预定义位置构建内容。它意味着像这样使用(This question也可能有用):
char *buffer = new char[sizeof(string)];
string *str = new (buffer) string("hello, world");//<-- this is your placement new
如您所见,您正在构建的内存应该事先获得。但是,在您的示例中,您没有这样做,并尝试写入您之前未获得的内存,这会导致段错误。
另外,正如另一个答案所提到的,您无法保证每次都获得b
的相同地址。而且,即使你很幸运,并且place
指向与b
相同的地址,你仍然会尝试写入不属于你的记忆,因为你做了{{1事先。