假设我有一个指针char* ptr
已分配内存和另一个指针char* arr = ptr
释放arr
内存后ptr
会发生什么。
让函数成为:
char* foo()
{
char* ptr = new char [100];
char* arr = ptr;
delete [] ptr;
return arr;
}
我可以使用此返回值吗?
是否会导致编译时/运行时错误? 或者其他任何东西。
如果函数是
会发生什么char* foo()
{
char* ptr = new char [100];
char* arr = ptr;
delete [] arr;
return ptr;
}
我想以前的输出没有变化,但会有任何改变吗?
如果我有课
,会发生什么class Pointer
{
public:
char* ptr;
Pointer()
{
ptr= new char [100];
}
~Pointer()
{
delete [] ptr;
}
};
和功能
Pointer foo()
{
Pointer ptr;
ptr.ptr[0]='l';
return ptr;
}
在函数结束时调用析构函数并创建一个悬空指针Pointer::ptr
??
答案 0 :(得分:4)
我可以使用此返回值吗?
您可以“使用”它,但不能取消引用它。例如,您可以打印指针值(但不是指向数据!):
std::cout << (intptr_t)foo() << std::endl; // OK
std::cout << foo(); // WRONG: this dereferences the pointer!
因此,虽然值可以“使用”,但它不再是指向char
的指针。
如果函数是[...]
会发生什么
两个函数具有相同的含义。在任何体面的编译器上,编译时都应该yield identical machine code。
arr
内存被解除分配后ptr
会发生什么?
没有任何反应:它的价值保持不变。但是因为指向的对象已被释放,所以它现在是一个悬空指针。所以你不能用它做任何事情:如果你这样做,你会得到未定义的行为。未定义的行为意味着任何事情都可能发生。这包括:没有任何事情发生(事情“显示为”工作正常“),或者让您的硬盘格式化。
情况也是如此,如果你在很多地方建造房屋。您向朋友Arr
提供GPS坐标。但在此期间你决定搬出去。然而你的朋友Arr
仍然有旧的坐标。现在Arr
决定使用它们。有几种可能的结果 - 你无法控制发生的结果。我将列出几个:
一小时前你搬出去了。一切都还是一样的。 Arr停了下来,拍了一张旧房子的照片,然后离开了。
这对应于由于重合,指向存储器仍包含可用内容的情况。你仍然有一个错误,但巧合隐藏了它。
你搬出去了,但是第二天,这个城市决定把这个地方夷为平地,并在它和邻近地段建造一个大型公寓大楼。你的朋友进来期待一个小房子,看到一个大公寓高楼,最终完全难倒。
这对应于重复使用内存,然后是悬空指针取消引用的情况。这是否导致CPU引发异常取决于之前居住的对象类型。
你搬出去了,但发生了地震,那里现在有一个湖。你的朋友陷入其中并淹死。
这对应于以前作为免费商店的一部分的现在冗余的虚拟内存块未被映射的情况。你出现页面错误。
内存管理器运行时可以释放用于支持指针指向的地址空间的页面。回想一下,通常C ++程序在虚拟内存机器上运行。程序看到的地址空间是虚拟地址空间。当没有支持给定虚拟地址空间页面的物理内存页面,并且没有该页面的文件或其他支持时,对它的任何访问都将导致页面错误传播到用户空间并在未处理时终止进程(默认情况下)
答案 1 :(得分:0)
从您的代码中,arr将指向未分配的内存,因此如果您尝试使用它,它将包含绝对随机的数据。
答案 2 :(得分:0)
我曾经在嵌入式系统上工作过,并且,有时会发生运气,当系统崩溃时,我在正确的时间(相对于删除)将调试器连接到正确的位置附近。代码是C ++,调试器是gdb,vxWorks是嵌入式系统工具套件。
我检查过的代码在某种程度上类似于你的问题,实际上是删除后指针的解除引用。
...
char* ptr = new char [100];
delete [] ptr;
// more stuff that did not affect what ptr pointed to
// about 5 to 9 lines later
char retVal = ptr[x]; // <<< invalid access crash
...
崩溃表明ptr [x]无效。
那个嵌入式系统(vxWorks)有技术来确认ptr指向的位置确实不再存在于上下文中,从该任务中取消映射。
我猜它不寻常(因为性能),但删除不仅从动态内存中释放了块,它还从线程内存空间释放了内存块,使得地址无效,导致总线错误。
我不知道如何在Linux中确认类似的信息。
释放ptr内存后arr会发生什么?
自动变量不受删除影响。
我可以使用此返回值吗?
行为未定义(即UB),因此您应该避免这样做。
是否会导致编译时/运行时错误?或者其他任何东西。
UB意味着任何其他事情都可能发生。