为什么资源被释放后仍然可以访问,程序没有崩溃?

  • 本文关键字:访问 程序 崩溃 资源 释放 c++
  • 更新时间 :
  • 英文 :

#include <iostream>
#include <string>
using namespace std;
static inline string BoolToString(bool boolean_exp) {
return boolean_exp? "True" : "False";
}
class Foo {
public:
explicit Foo(int _size) noexcept : 
my_resource(new int[_size]) {
cout << "Foo obj init, at: " << this << ", my_resource at:" << my_resource <<endl;
my_resource[0] = 1234567;
}
~Foo() {
cout << "A Foo instance at: " << this << " is finalizing; ";
cout << "my_resource: " << my_resource << endl;
delete[] my_resource;
my_resource = nullptr;
}
public:
int *my_resource = nullptr;
};
void function_foo(Foo f) {
cout << "function_foo() invoked" << endl;
}
int main(int argc, char *argv[]) {
Foo foo(20);
function_foo(foo); // I think, foo's copy should released after function_foo() return-ed, my_resource should be nullptr;
cout << "Is foo.my_resource released?: " << BoolToString(foo.my_resource == nullptr) << endl;
cout << (*foo.my_resource) << endl;
return 0;
}

显然,在主函数中调用function_foo函数后,foo的一个浅拷贝被作为参数传递给function_foo,并且该浅拷贝应该在function_foo完成后被解构。函数完成运行后,foo中的my_resource字段(在主函数中声明)仍然可以解析并获得值1234567,我想知道为什么会这样?

我的想法是,虽然my_resource指向的内存资源在临时对象被解构时被释放,但该内存资源不会被回收或覆盖,因此它仍然可以在错误的中访问。道路
编译器做了不该做的事吗?

顺便说一下,我使用clang++作为编译器,开发环境是windows。

编译:clang++ file.cxx -o file.exe运行:./file结果:

Foo obj init, at: 0x61fdd8, my_resource at:0x1f1e90
function_foo() invoked
A Foo instance at: 0x61fdd0 is finalizing; my_resource: 0x1f1e90
is foo.my_resource released?: False
1234567
A Foo instance at: 0x61fdd8 is finalizing; my_resource: 0x1f1e90

函数运行完成后,foo中的my_resource字段(在主函数中声明)仍然可以被解析并获得值1234567我想知道为什么会这样?

这是一个未定义的行为,所以如果你不走运,它可能会起作用。

在典型的c++实现中,这很有可能不会崩溃,因为分配的内存比页面小,并且不需要分配器将内存返回给操作系统。这意味着您的进程仍然能够读取该地址。

此外,编译器没有决定将该地址用于其他内容,因此恰好该值仍然存在。

内存资源释放,但这并不意味着它消失了!它只是被标记为"空闲内存"下一次你的程序试图分配内存的时候,它可能会得到那块内存。所以,是的…它还在那儿……现在……但是你不应该依赖它,因为你无法预测它将来会发生什么。

c++不会费心去"锁定访问";或者只是"擦除";释放的内存,因为这只会占用CPU周期,没有任何实际的好处。在你释放了内存之后,无论如何你都不应该再碰它。

最新更新