可能重复:
C++ delete - It deletes my objects but I can still access the data?
我很好奇为什么我使用以下(相当人为的)代码获得以下行为。我在用 关于Ubuntu 10.10的gcc 4.4.5
#include <iostream>
int main(int argc, char *argv[])
{
int N = 5;
int *myarr = new int[N];//create an integer array of size 5
for (int i = 0; i < N; ++i)
{
myarr[i] = 45;
std::cout << myarr[i] << std::endl;
}
delete[] myarr;//kill the memory allocated by new
std::cout << "Let's see if the array was deleted and if we get a segfault \n" ;
for (int i = 0; i < N; ++i)
{
std::cout << myarr[i] << std::endl;
}
return 0;
}
即使使用-Wall
标志,代码也会编译。输出是
Desktop: ./a.out
45
45
45
45
45
Let's see if the array was deleted and if we get a segfault
0
0
45
45
45
Desktop:
为什么仍然可以访问myarr
数组,就像它在没有段错误的情况下被删除一样?
此外,即使myarr
数组被删除,为什么值45似乎仍然在2,3和4位正确打印。
简而言之delete[]
真正在这里做什么?
答案 0 :(得分:3)
delete[]
为数组中的每个元素调用析构函数,并告诉您的计算机您将不再使用该内存。记忆仍然在那里,你不允许使用它。
您所看到的是未定义的行为。它可能会以各种方式失败,但由于你的程序很短,它可能会像你在大多数时候看到的那样工作。
答案 1 :(得分:2)
释放内存不保证在以后尝试访问该内存时会出现段错误。基本上,在释放内存后访问内存会导致未定义的行为 - 任何事情都可能发生。
在您的情况下,delete[]
运算符释放内存并将其返回到运行时库。但是,运行时库会挂起到内存中,并且不会立即将其返回给操作系统(毕竟,您可能很快就会再次需要它)。运行时库将使用应用程序已释放的内存来管理自己的数据结构。例如,您看到的零可能是自由列表结构的一部分。
答案 2 :(得分:1)
运算符delete[]
仅释放内存。 delete[]
未定义行为后访问内存。
myarr
指向的内存可能仍会包含您暂时分配的值。该内存地址将包含相同的值,直到有人向其写入内容。
答案 3 :(得分:1)
内存被取消分配,其中一些已经消失了,你可以看到。它仍然可以被访问,但你的程序没有崩溃这一事实主要是因为没有足够的时间为这个内存分配不同的对象,或者你没有尝试做任何顽皮的事情,比如在其中使用一个值作为缓冲区或其他东西的偏移量。
答案 4 :(得分:0)
您认为delete[]
做了什么?它调用数组中所有对象的析构函数,然后释放它。你的myarr
指针现在指向释放的内存,并且是一个无效的指针。
显然,内存尚未被重用,因此它仍然包含释放之前存在的数据,但这是未定义的行为,这意味着您不能依赖它。如果你这样做,你有一天会有各种令人兴奋的难以发现的错误。
答案 5 :(得分:0)
delete []调用析构函数,然后告诉系统先前分配的内存不会被进一步使用,但指针仍然指向起始地址。
#include <iostream>
int main(int argc, char *argv[])
{
int N = 5;
int *myarr = new int[N];//create an integer array of size 5
for (int i = 0; i < N; ++i)
{
myarr[i] = 45;
std::cout << myarr[i] << std::endl;
}
delete[] myarr;//kill the memory allocated by new
std::cout << "Let's see if the array was deleted and if we get a segfault \n" ;
int *dumb = new int[N];
dumb[3]=0;
for (int i = 0; i < N; ++i)
{
std::cout << myarr[i] << std::endl;
}
return 0;
}
,输出为:
45
45
45
45
45
Let's see if the array was deleted and if we get a segfault
0
45
45
0
45
您没有出现分段错误,因为内存太小而且可能未被其他进程保留。但试试这个:
#include <iostream>
int main(int argc, char *argv[])
{
int N = 50000;
int *myarr = new int[N];//create an integer array of size 5
for (int i = 0; i < N; ++i)
{
myarr[i] = 45;
std::cout << myarr[i] << std::endl;
}
delete[] myarr;//kill the memory allocated by new
std::cout << "Let's see if the array was deleted and if we get a segfault \n" ;
std::cin >> N;
int *dumb = new int[N];
dumb[3]=0;
for (int i = 0; i < N; ++i)
{
std::cout << myarr[i] << std::endl;
}
return 0;
}
并输入一些数字,例如9000
答案 6 :(得分:0)
这里所写的一切都是真的,我只想更多地了解为什么你所做的是未定义的行为。
请记住,我上面写的所有内容都只是非常简化的版本,它比那复杂得多,但我希望它会让你知道这一切是如何工作的“引擎盖下”。 阿门。