出于乐趣,我决定看看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?
答案 0 :(得分:2)
当您尝试访问操作系统禁止您访问的地址时,会发生段错误。这可能是因为地址后面的mem没有分配给你进程,或者因为它不存在或者其他什么。因此,您现在正在尝试访问仍分配给您的进程的内存,因此不会出现段错误。
Malloc(管理堆的那个)使用某些缓冲区来限制系统调用的数量。所以你可以访问未初始化的mem。
答案 1 :(得分:2)
您将无效的此指针传递给print,但它永远不会被取消引用,因为print不是虚拟的,也不会访问任何成员。