WAR*_*ead -1 c++ pointers dynamic-allocation
假设我有一个指针char* ptr分配了内存和另一个指针char* arr = ptr
释放内存arr后会发生什么ptr。
让函数为:
char* foo()
{
char* ptr = new char [100];
char* arr = ptr;
delete [] ptr;
return arr;
}
Run Code Online (Sandbox Code Playgroud)
我可以使用这个返回值吗?
它会导致任何编译时/运行时错误吗?或者其他任何东西。
或者如果函数是
char* foo()
{
char* ptr = new char [100];
char* arr = ptr;
delete [] arr;
return ptr;
}
Run Code Online (Sandbox Code Playgroud)
我想以前的输出不会有任何变化,但会有任何变化吗?
如果我有一堂课会发生什么
class Pointer
{
public:
char* ptr;
Pointer()
{
ptr= new char [100];
}
~Pointer()
{
delete [] ptr;
}
};
Run Code Online (Sandbox Code Playgroud)
和功能
Pointer foo()
{
Pointer ptr;
ptr.ptr[0]='l';
return ptr;
}
Run Code Online (Sandbox Code Playgroud)
不会在函数末尾调用析构函数并创建一个悬空指针Pointer::ptr吗??
我可以使用这个返回值吗??
您可以“使用”它,但不能取消引用它。例如,您可以打印出指针值(但不是指向的数据!):
std::cout << (intptr_t)foo() << std::endl; // OK
std::cout << foo(); // WRONG: this dereferences the pointer!
Run Code Online (Sandbox Code Playgroud)
因此,虽然可以“使用”该值,但它不再用作指向的指针char。
或者如果函数是 [...]
这两个函数具有相同的含义。在任何体面的编译器上,您应该期望两者在编译时产生相同的机器代码。
内存被释放
arr后会发生什么ptr?
它什么也没发生:它的值保持不变。但是因为指向的对象已经被释放,它现在是一个悬空指针。所以你不能将它用于任何事情:如果你这样做,你会得到未定义的行为。未定义的行为意味着任何事情都可能发生。这包括:没有发生任何事情(事情“似乎”“工作正常”),或格式化您的硬盘驱动器。
如果你在很多地方建房子,情况是一样的。你给你的朋友ArrGPS 坐标。但与此同时,你决定搬出去。然而你的朋友Arr仍然拥有旧坐标。现在Arr决定使用它们。有几种可能的结果 - 您无法控制发生哪一种。我只列出几个:
你一个小时前搬走了。一切都还是一样。Arr 路过,拍了一张你老房子的照片,然后离开了。
这对应于由于巧合,指向的存储器仍然包含可用内容的情况。你仍然有一个错误,但巧合隐藏了它。
你搬出去了,但第二天市政府决定将这块地夷为平地,并在其上和相邻地块上建造一座大型公寓楼。你的朋友进来期待一个小房子,看到一个大的高层公寓,结果完全被难住了。
这对应于内存被重用,然后是悬空指针取消引用的情况。这是否会导致 CPU 引发异常取决于之前存在于那里的对象类型。
你搬出去了,但发生了地震,现在那里有一个湖。你的朋友掉进去淹死了。
这对应于这样一种情况,即曾经是空闲存储的一部分的现在冗余的虚拟内存块已被取消映射。你得到一个页面错误。
内存管理器运行时可以释放用于支持指针指向的地址空间的页面。回想一下,C++ 程序通常运行在虚拟内存机之上。程序看到的地址空间就是虚拟地址空间。当没有物理内存页面支持给定的虚拟地址空间页面,并且该页面没有文件或其他支持时,对它的任何访问都会导致页面错误传播到用户空间并在未处理时终止进程(默认情况下) .