访问已经销毁的对象不会导致段错误
Accessing an already destroyed object does not cause segfault
出于乐趣,我决定看看 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 标志构建):
Destroyed!
Hello!
在堆中分配 d 并删除它会导致相同的行为(即不会崩溃)。
我假设内存没有被覆盖,C++ 'tricked' 可以正常使用它。但是,令我惊讶的是,在堆上分配和删除时,可以使用未分配给它们的内存。
有人可以对此提供更多见解吗?这是否意味着当尝试取消引用指针时,如果该内存恰好有一些东西 'coherent' 对于我们的上下文,尽管内存没有分配给我们,执行也不会导致 SEGFAULT?
当您尝试访问 OS 禁止您访问的地址时,会发生段错误。这可能是因为地址后面的内存未分配给您的进程,或者因为它不存在或其他原因。所以你现在正试图访问一块仍然分配给你的进程的内存,所以没有段错误。
Malloc(管理堆的那个)与某些缓冲区一起工作以限制系统调用的数量。所以有未初始化的内存你可以访问。
您向 print 传递了一个无效的 this 指针,但它从未被取消引用,因为 print 不是虚拟的,也没有访问任何成员。
出于乐趣,我决定看看 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 标志构建):
Destroyed!
Hello!
在堆中分配 d 并删除它会导致相同的行为(即不会崩溃)。
我假设内存没有被覆盖,C++ 'tricked' 可以正常使用它。但是,令我惊讶的是,在堆上分配和删除时,可以使用未分配给它们的内存。
有人可以对此提供更多见解吗?这是否意味着当尝试取消引用指针时,如果该内存恰好有一些东西 'coherent' 对于我们的上下文,尽管内存没有分配给我们,执行也不会导致 SEGFAULT?
当您尝试访问 OS 禁止您访问的地址时,会发生段错误。这可能是因为地址后面的内存未分配给您的进程,或者因为它不存在或其他原因。所以你现在正试图访问一块仍然分配给你的进程的内存,所以没有段错误。
Malloc(管理堆的那个)与某些缓冲区一起工作以限制系统调用的数量。所以有未初始化的内存你可以访问。
您向 print 传递了一个无效的 this 指针,但它从未被取消引用,因为 print 不是虚拟的,也没有访问任何成员。