为什么在成员函数调用上没有段错误
Why no segfault on member function call?
我正在寻找对这段代码的澄清。对 A::hello() 的调用有效(我期望一个 segv)。段错误确实在访问成员 x 时出现,因此似乎仅方法解析实际上并没有取消引用 bla?
我在关闭优化的情况下编译,gcc 4.6.3。为什么bla->hello()不爆炸?只是想知道发生了什么。谢谢。
class A
{
public:
int x;
A() { cout << "constructing a" << endl; }
void hello()
{
cout << "hello a" << endl;
}
};
int main()
{
A * bla;
bla = NULL;
bla->hello(); // prints "hello a"
bla->x = 5; // segfault
}
程序表现出未定义的行为。"似乎有效"是未定义行为的一种可能表现。
特别是,bla->hello()
调用似乎有效,因为hello()
实际上并没有以任何方式使用this
,所以它恰好没有注意到this
不是有效的指针。
您正在取消引用NULL
指针,即尝试访问存储在地址 NULL
的对象:
bla = NULL;
bla->hello();
bla->x = 5;
这会导致未定义的行为,这意味着任何事情都可能发生,包括将5
分配给成员x
时的 SEG 错误,以及在调用 hello
方法时包括欺骗性的"按预期工作"效果。
至少在典型的实现中,当您通过指针调用非虚拟成员函数时,不会取消引用该指针来查找该函数。
指针的类型用于确定在其中搜索函数名称的范围(上下文),但这完全在编译时发生。指针指向的内容(在空指针的情况下包括"无")与查找函数本身无关。
编译器找到正确的函数后,通常会将像 a->b(c);
这样的调用转换为大致等效的内容:b(a, c);
-- 然后a
成为函数内 this
的值。当函数引用对象中的数据时,this
被取消引用以查找正确的对象,然后通常应用偏移量以在该对象中查找正确的项。
如果 member 函数从不尝试使用对象的任何成员,则 this
是 null 指针这一事实不会影响任何内容。
另一方面,如果成员函数确实尝试使用对象的成员,它将尝试取消引用this
执行此操作,如果this
是 NULL 指针,则不起作用。同样,调用虚函数始终使用对象中的 vtable 指针,因此尝试通过空指针调用虚函数可能会失败(无论虚函数中的代码是否引用对象中的数据)。
正如我所说,我在这里谈论的是典型的实现。从标准的角度来看,你只是有未定义的行为,这就是它的结束。从理论上讲,实现不必按照我描述的方式工作。然而,实际上,基本上所有相当流行的C++实现(例如,MS VC++,g++,Clang和Intel)在这些方面都非常相似。
只要成员函数不取消引用this
,调用它通常是"安全的",但你处于未定义的行为状态。
理论上,这是未定义的行为。实际上,您在调用hello()
时不使用指针this
它根本不引用您的类,因此可以工作并且不会生成内存访问冲突。但是,当您执行bla->x
时,您正在尝试通过未初始化bla
指针引用内存,并且它崩溃了。同样,即使在这种情况下,也不能保证它会崩溃,这是未定义的行为。
- 编写代码时C++出现错误:错误 1 错误 C2601:'circle':本地函数定义是非法的
- 如何摆脱C ++中的分段错误错误?
- Clang 8 带有静态 constexpr 和数组的链接器错误 - 错误是什么以及如何解决它?
- 为什么每当我尝试运行此链接列表删除功能时都会收到分段错误错误?
- 如何解决分段错误错误C++
- 作为参数模板的模板类:MSVC 错误 - 错误 C2977:模板参数过多 (C++98)
- 安卓工作室 |CPP 文件错误错误: 位图库中对"AndroidBitmap_unlockPixels"的未定义引用
- 卷曲给出分段错误错误
- 无法访问 Arduino 结构字段。错误"退出状态 1。xxxx 不命名类型"
- 错误错误 C2872:"布尔值":kinect.h 的不明确符号
- C++打印模板容器错误(错误:"运算符<<"的不明确重载)理解?
- 结构的分割错误错误
- 为什么此代码返回分段错误错误?
- 错误错误:无法编译内置功能
- 分段错误错误C++
- C++ 1Z 错误:错误:演绎指南中声明中的显式限定
- 使用对数据类型的向量的哈希表中的分段错误错误
- 为什么此代码会导致分段错误错误
- JNA结构字段值错误
- C++段故障错误