如果内存被释放,指针的状态

state of pointer if memory is deallocated

假设我有一个指针 char* ptr 分配的内存和另一个指针 char* arr = ptr

ptr 内存被释放后 arr 会发生什么。

设函数为:

char* foo()
{
    char* ptr = new char [100];
    char* arr = ptr;
    delete [] ptr;
    return arr;
}

我可以使用这个返回值吗?

它会导致任何 compile-time/Run-time 错误吗? 或者其他任何事情。

或者如果函数是

会发生什么
char* foo()
{
    char* ptr = new char [100];
    char* arr = ptr;
    delete [] arr;
    return ptr;
}

我想与之前的输出相比不会有任何变化,但会有任何变化吗??

如果我有 class

会怎样
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 ??

Can I use this returned value??

您可以 "use" 它,但不能取消引用它。例如,您可以打印出指针值(但不是指向的数据!):

std::cout << (intptr_t)foo() << std::endl; // OK
std::cout << foo(); // WRONG: this dereferences the pointer!

因此,虽然值可以是 "used",但作为指向 char 的指针已不再有用。

Or what would happen if the function was [...]

两个函数意义相同。在任何体面的编译器上,您应该期望两者在编​​译时都 yield identical machine code

What happens to arr after ptr memory is deallocated?

它没有任何反应:它的值保持不变。但是因为指向的对象已经被释放,它现在是一个悬空指针。所以你不能用它做任何事情:如果你这样做,你会得到未定义的行为。未定义的行为意味着任何事情都可能发生。这包括:没有任何反应(事情 "appear" 到 "work OK"),或者格式化你的硬盘。

如果你在地块上盖房子,情况是一样的。您将 GPS 坐标提供给您的朋友 Arr。但与此同时你决定搬出去。但是你的朋友 Arr 仍然有旧坐标。现在 Arr 决定使用它们。有几种可能的结果——您无法控制哪一种发生。我将列出一些:

  1. 你一个小时前搬走了。一切还是一样。 Arr路过,拍了你老家的照片就走了。

    这对应于一种情况,由于巧合,指向的内存仍然包含可用的内容。你仍然有一个错误,但巧合隐藏了它。

  2. 你搬走了,但第二天市政府决定将这块地夷为平地,并在其上和附近的地块上建造一座大型公寓楼。你的朋友进来期待一个小房子,看到一个大公寓高层,结果完全被难住了。

    这对应于内存被重用然后取消引用悬垂指针的情况。这是否会导致 CPU 引发异常取决于之前存在的对象类型。

  3. 你搬出去了,但是地震了,现在那里有一个湖。你的朋友掉下去淹死了。

    这对应于现在冗余的虚拟内存块(曾经是免费存储的一部分)已被取消映射的情况。您遇到页面错误。

    内存管理器运行时可以释放用于支持指针指向的地址 space 的页面。回想一下,C++ 程序通常在虚拟内存机之上运行。程序看到的地址space就是虚拟地址space。当没有物理内存页面支持给定的虚拟地址 space 页面,并且没有文件或该页面的其他支持时,对其的任何访问都会导致页面错误传播到用户空间并在未处理时终止进程(因为它默认情况下)。

根据您的代码,arr 将指向未分配的内存,因此如果您尝试使用它,它将包含绝对随机的数据。

我曾经在嵌入式系统上工作过,有时运气不错,当系统崩溃时,我在正确的时间(相对于删除)在正确的位置附近连接了调试器。代码是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 指向的地方确实不再在上下文中,从那个任务中取消映射。

我猜这很不寻常(因为性能),但是删除不仅从动态内存中释放了块,还从线程内存中释放了内存块space,使地址无效,导致总线错误。

我不知道如何确认Linux中的类似信息。


What happens to arr after ptr memory is deallocated?

自动变量不受删除影响。


Can I use this returned value?

行为未定义(即 UB),因此您应该避免这样做。


Will it cause any compile-time/Run-time error? Or any thing else.

UB 意味着任何其他事情都可能发生。