出于好玩,我决定看看gdb会怎么评价这段代码,这段代码旨在尝试使用已经销毁的对象的方法。
#include <iostream>
class ToDestroy
{
public:
ToDestroy() { }
~ToDestroy() {
std::cout << "Destroyed!" << std::endl;
}
void print() {
std::cout << "Hello!" << std::endl;
}
};
class Good
{
public:
Good() { }
~Good() { }
void setD(ToDestroy* p) {
mD = p;
}
void useD() {
mD->print();
}
private:
ToDestroy* mD;
};
int main() {
Good g;
{
ToDestroy d;
g.setD(&d);
}
g.useD();
return 0;
}
输出为(使用-O0标志构建):
被摧毁了!
你好!
在堆中分配d并删除它会导致相同的行为(即,没有崩溃)。
我认为内存没有被覆盖,C++被"欺骗"而正常使用它。然而,我感到惊讶的是,在对堆进行分配和删除时,可以使用未分配给它们的内存。
有人能对此提供更多见解吗?这是否意味着,当试图取消引用指针时,如果该内存恰好对我们的上下文具有"连贯性",则尽管内存没有分配给我们,但执行不会导致SEGFAULT?
当您试图访问操作系统禁止您访问的地址时,会发生segfault。这可能是因为地址后面的内存没有分配给您的进程,也可能是因为它不存在或其他原因。因此,您现在正试图访问一段仍分配给进程的内存,因此没有segfault。
Malloc(管理堆的那个)使用某些缓冲区来限制系统调用的数量。因此,您可以访问未初始化的内存。
您向print传递了一个无效的this指针,但它从未被取消引用,因为print不是虚拟的,也没有访问任何成员。