C++ 为什么资源在发布后仍然可以访问,并且程序没有崩溃?
内存资源被释放,但这并不意味着它消失了!它只是标记为“空闲内存”,下一次程序中的某些内容试图分配内存时,它可能会得到该内存。所以,是的。。。它还在那里。。。现在。。。但你不应该依赖它,因为你无法预测未来它会发生什么 C++不必费心以某种方式“锁定访问”,甚至只是“擦除”释放的内存,因为这只会占用CPU周期,没有任何实际的好处。在你释放记忆后,无论如何你都不应该去碰它 在函数完成运行后,foo中的my_resource字段(在主函数中声明)仍然可以被解析并获得值1234567。我想知道为什么会这样 这是一种未定义的行为,因此,如果你运气不好,它可能会起作用C++ 为什么资源在发布后仍然可以访问,并且程序没有崩溃?,c++,C++,内存资源被释放,但这并不意味着它消失了!它只是标记为“空闲内存”,下一次程序中的某些内容试图分配内存时,它可能会得到该内存。所以,是的。。。它还在那里。。。现在。。。但你不应该依赖它,因为你无法预测未来它会发生什么 C++不必费心以某种方式“锁定访问”,甚至只是“擦除”释放的内存,因为这只会占用CPU周期,没有任何实际的好处。在你释放记忆后,无论如何你都不应该去碰它 在函数完成运行后,foo中的my_resource字段(在主函数中声明)仍然可以被解析并获得值1234567。我想知道为什么会这样
在典型的C++实现中,这有很好的机会不会崩溃,因为分配小于页面,分配器不需要将内存返回操作系统。这意味着您的进程仍然能够读取该地址
此外,编译器没有决定将地址用于其他内容,因此碰巧值仍然存在。“编译器做了不该做的事情”。不,你做了你不该做的事。编译器没有编写无效的程序。是的。编译器只是编译了它。“或者更确切地说,编译器做了它不应该做的事情。”-编译器不负责避免未定义的行为;这就是你的角色。是的,检测到故障,但不是编译器。C++允许你拥有巨大的自由度,包括能够自由地打破规则并进入未定义的行为的能力。这样做是你的责任。如果有人告诉你你的程序会崩溃,他们是天真的。它可能会崩溃。可能不会。它可以做很多事情。这就是UB的本质。
#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;
}
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