【问题标题】:Deleted variable can still be accessed in c++? [duplicate]删除的变量仍然可以在 C++ 中访问? [复制]
【发布时间】:2021-12-29 07:01:22
【问题描述】:

我创建了一个简单的项目只是为了测试删除变量的工作原理,但我遇到了一件奇怪的事情...... 我创建了三个 int 变量(1 个基于堆栈和 2 个基于堆),当我使用 delete 删除堆变量时,我仍然可以访问它们。我可以打印它们或更改它们的值,但如何?删除不应该从内存中永久删除变量,还有另一个问题....为什么不能使用 free()delete 删除基于堆栈的变量?

这是 (C++) 脚本 -

#include<iostream>
using namespace std;

void Stuff()
{
   int* heap_int = (int*)malloc(4); //Heap based variable
   *heap_int = 500;

   int  stack_int = 5; //Stack based variable

   int* calloc_int = (int*)calloc(1,2); //Heap based variable
   *calloc_int = 600;
  
  std::cout << "Value (HeapInt) : " << *heap_int << "\n"; //Prints 500
  std::cout << "Value (CallocInt) : " << *calloc_int << "\n"; //Prints 600
  std::cout << "Value (StackInt) : " << stack_int << "\n"; //Prints 5

  delete heap_int;
  delete calloc_int;
  //delete stack_int; (will not work)

  std::cout << "\nValue after delete (HeapInt) : " << *heap_int << "\n"; //Still prints 500
  std::cout << "Value after delete (CallocInt) : " << *calloc_int << "\n"; //Still Prints 600
  std::cout << "Value after delete (StackInt) : " << stack_int << std::endl; //Prints 5
 
  *heap_int = 82;
}

int main()
{
  Stuff();
}

我在在线教程中听说,基于堆的变量只有在我们使用 deletefree() 时才会被释放(不像堆栈变量在其作用域结束时自动释放)那为什么我不能像这样访问基于堆的变量超出范围...?

#include<iostream>

void Function()
{
  int* variable = new int;
  *variable = 6;
}

int main()
{
   *variable = 9; //Error says "Use of Undeclared identifier variable"
}

【问题讨论】:

  • 当您调用deletefree 时,并不意味着内存位置消失得无影无踪。该位置仍然存在,只是访问它是未定义的行为。
  • malloc 不是 C++。 mallocfree 一起使用,其中deletenew 一起使用,构造函数、析构函数和其他东西。
  • @Sandburg 从技术上讲,malloc 仍然存在,但您无法使用它创建对象。请注意,C++ 核心指南建议不要使用 new/delete,而是使用 std::make_unique 以避免内存泄漏和对指针的明确所有权进行建模。 (isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines 并查找与 new/delete/pointers 相关的内容)
  • 在 C++ 范围内定义得非常好,在一个范围内声明的任何变量都不能在该范围外访问。所以至少在 C++ 中应该是这样的。注意:不要使用“使用命名空间标准”
  • 啊!抱歉....我忘了删除 using namespace std ????顺便说一句,感谢所有回答的人

标签: c++ heap-memory


【解决方案1】:

读取free'd 或deleted 内存地址的内容称为未定义行为

  delete heap_int;

  std::cout << "\nValue after delete (HeapInt) : " << *heap_int << "\n"; //Still prints 500

可能仍然能够在已删除的地址处看到以前的值,但绝对不能保证。一旦下一个 malloc/new 发生(或技术上的任何时候),内存管理器可能会将该地址重新用于另一个对象并覆盖那里的内容。

还有这个:

*heap_int = 82;

同样,写入已删除地址是更糟糕的未定义行为 - 您很有可能以奇怪的方式破坏了程序的行为,或者充其量是快速崩溃。

为什么我不能像这样访问超出范围的基于堆的变量...?

因为您无法访问不在您的范围或父范围内的任何变量。在您的情况下,main 中的代码只能访问该函数中的变量或在全局范围内声明的变量。这就是范围的全部意义!

【讨论】:

    猜你喜欢
    • 2016-03-07
    • 2011-12-11
    • 2020-12-20
    • 2013-04-12
    • 1970-01-01
    • 2011-05-23
    • 2021-08-11
    • 1970-01-01
    相关资源
    最近更新 更多