【问题标题】:Why delete pointer to stack is error?为什么删除指向堆栈的指针是错误的?
【发布时间】:2016-11-14 03:13:30
【问题描述】:

我已阅读主题Calling delete on variable allocated on the stack 而且我知道在堆栈中使用运算符删除时,请参阅错误。但我想知道更多更深入的信息。为什么会出错?

【问题讨论】:

  • 你需要先知道什么是栈。如果您删除堆栈中的内存,您的堆栈将不再连续,但运行时依赖于这一事实
  • 不同不一样。 ——弗雷德·皮克尔
  • 你没有delete一个你没有new的指针。没有比这更深的了,这就是语言的规则。
  • 链接问题的已接受答案的哪一部分对您来说没有意义?

标签: c++ stack delete-operator


【解决方案1】:

堆栈创建的对象是自动的,而非堆栈创建的对象(使用关键字new)是动态的,需要使用关键字delete 进行回收。

堆栈上的对象由系统自动回收,使用不同的机制到使用关键字new动态分配的对象。

因此,使用关键字new 调用关键字delete 并使用未动态 分配的对象地址势必会造成麻烦。

【讨论】:

    【解决方案2】:

    C++ 运行时库中隐藏(不是很深)的是一种称为堆的数据结构。堆的工作(无论如何,从概念上讲)是从一个巨大的字节数组开始,并在您的程序请求时将该数组的块分配给您的程序。这样您就不必自己实现任何块管理代码(这很好,因为在所有情况下正确有效地处理它是一项不平凡的编码任务)。

    每当您的程序调用new 运算符时,对堆代码的调用会切掉该数组的一部分(再次从概念上讲)并将其交给您的程序使用。相反,当您稍后调用 delete 运算符时,该字节子数组将返回给堆,堆的代码可以将其与大数组的相邻部分(如果相邻部分中的一个或两个)重新合并到一起也可用)或至少保留其可用性记录,以便以后通过随后调用new 重新使用它。

    然而,堆栈上的对象并不位于堆的巨型数组中;相反,它们位于堆栈上。因此,当您在堆栈对象上调用delete 时,您正在将一块内存交给堆,而该内存从一开始就不是其资源池的一部分。 C++ 语言设计者可能要求每个堆实现必须检查这种情况并做一些可预测的响应(例如忽略未知指针,或打印错误消息,或触发断言失败并终止程序),但是做对每个delete 进行这样的检查可能效率低下,C++ 语言优先考虑在运行时尽可能保持高效。因此,传递一个指向delete 的指针,该指针以前没有由new 返回,会调用未定义的行为,这意味着C++ 运行时库的设计者不必关心他的堆代码会做什么在那种情况下,因为这种情况从一开始就不应该发生——只有当你犯了编程错误时才会发生这种情况。所以,不要犯那个错误,因为它会导致你的程序以你不希望的方式运行。

    【讨论】:

      【解决方案3】:

      要正确理解它,您应该首先了解什么是堆栈以及堆的含义。通过this 了解进程内存是如何对齐的。

      当你调用一个函数时,它会从进程的虚拟内存中接收连续的内存块。它用于接收参数、定义局部变量和存储返回地址等。一旦函数完成执行并返回,该内存就会被释放。这称为堆栈。

      堆分配是在运行时完成的。因此不能保证它是连续的。 new 函数调用从空闲池中为您找到合适的内存块,删除将其返回到空闲内存池。

      由于堆栈和堆在物理上是不同的实体,所以在堆上定义的操作不应该在堆栈上执行,因为这会导致运行时出现未定义的行为,正如 Jeremy Friesner 所解释的那样。作为一个经验法则,最好尽早报告错误,这是编译器在发现堆栈上定义的对象调用 delete 时所做的。

      【讨论】:

      • 一个有用的编译器可能会报告错误,但这不是必需的,所以你不能依赖它。
      猜你喜欢
      • 1970-01-01
      • 2018-04-14
      • 2019-08-27
      • 2020-06-09
      • 2023-04-01
      • 2012-02-05
      • 2012-07-23
      • 2010-12-19
      • 2018-05-02
      相关资源
      最近更新 更多