为什么编译和运行时都不能检测到这个问题呢. 为什么一个空指针还能够调用对象的成员函数呢? 我们要看看汇编代码. MyClass::Foo() 其实是一个全局函数, 在符号表中的名字是 "_ZN7MyClass2FooEv". 所以调用时并不需要通过对象指针. 不过在调用这个函数时,会传递对象指针进去. 函数的定义: .globl _ZN7MyClass3FooEv .type _ZN7MyClass3FooEv, @function _ZN7MyClass3FooEv: .LFB1442: pushl %ebp .LCFI4: movl %esp, %ebp .LCFI5: subl $8, %esp .LCFI6: subl $8, %esp pushl $_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_ subl $12, %esp pushl $.LC0 pushl $_ZSt4cout .LCFI7: call _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc addl $20, %esp pushl %eax .LCFI8: call _ZNSolsEPFRSoS_E addl $16, %esp leave ret 函数的调用: ptr = NULL; ptr->Foo(); return 0; 对应的汇编 movl $0, -4(%ebp) ;; ptr = NULL; subl $12, %esp ;; 通过堆栈进行参数传递,传入ptr. 不过Foo()没有用到它. pushl -4(%ebp) ;; call _ZN7MyClass3FooEv ;; ptr->Foo() addl $16, %esp movl $0, %eax ;; return 0 leave ret 通过上面的分析,我们明白了为什么这个让人迷惑的语句可以通过编译和运行了. 如果Foo()访问对象的成员,那么肯定是会出错的. 因为Foo()需要使用传入的ptr,而ptr的值是NULL. 比如 void Foo() { cout<<"MyClass::Foo() is invoked!"<
<
检测不了的错误(2) --- 分析
最新推荐文章于 2021-09-14 18:21:02 发布