aProperty) 这样的表达式会报错吗?

#include <iostream>

using namespace std;

class TestProperty{

public:int mp1;int mp2;int mp3;};void testProperty(){cout<<&(((TestProperty*)0)->mp1)<<endl;cout<<&(((TestProperty*)0)->mp2)<<endl;cout<<&(((TestProperty*)0)->mp3)<<endl;cout<<((TestProperty*)0)->mp1<<endl;

}

以上几个表达式能正常输出吗,如果能,输出的又是什么呢?

这是前三个表达式的输出,最后一个会造成程序的崩溃

编译器看到&(((TestProperty*)0)->mp1)这个表达式的时候,知道这句是为了获取mp1的地址,而此时,地址是知道的,所以就直接打印出来了,下面对应的汇编代码

73: cout<<&(((TestProperty*)0)->mp1);00401808 push 00040180A mov ecx,offset std::cout (0047eea0)0040180F call @ILT+75(std::basic_ostream<char,std::char_traits<char> >::operator<<) (00401050)74: cout<<&(((TestProperty*)0)->mp2);00401814 push 400401816 mov ecx,offset std::cout (0047eea0)0040181B call @ILT+75(std::basic_ostream<char,std::char_traits<char> >::operator<<) (00401050)75: cout<<&(((TestProperty*)0)->mp3);00401820 push 800401822 mov ecx,offset std::cout (0047eea0)00401827 call @ILT+75(std::basic_ostream<char,std::char_traits<char> >::operator<<) (00401050)

其中的0 4 8 就是编译器已经算好的地址,准确的说,是偏移地址,相对于类首地址的偏移地址

那为何 最后一句会崩呢,下面是对应的汇编代码

76: cout<<((TestProperty*)0)->mp1;0040182C mov eax,[00000000]00401831 push eax00401832 mov ecx,offset std::cout (0047eea0)00401837 call @ILT+275(std::basic_ostream<char,std::char_traits<char> >::operator<<) (00401118)

此时编译器认为是想取得mp1的内容,而此时mp1还没分配好内存空间,于是在调用mov eax,[00000000]的时候,发生访问异常了。

把代码修改一下

class TestProperty{public:int mp1;int mp2;int mp3;public:void func1(){printf("hello TestProperty");}};void testProperty(){(((TestProperty*)0)->func1());printf("%d",((TestProperty*)0)->func1);//vc6可以这么写,但在vs2013中这么会报错}

会正常输出吗?

为何第一句不会崩?因为方法早在类还没初始化的时候,已经在代码区生成了,它与类的构造没有关系,看对应的汇编代码

76: (((TestProperty*)0)->func1());004013E8 xor ecx,ecx004013EA call @ILT+0(TestProperty::func1) (00401005)77: printf("%d\n",((TestProperty*)0)->func1);004013EF push offset @ILT+0(TestProperty::func1) (00401005)004013F4 push offset string "%d\n" (0043401c)004013F9 call printf (00409260)

由于在调用func1的时候,应该在ecx传入调用者的地址,而这里为0,所以直接xor ecx,ecx对其清空了,,然后正常的调用了func1,但如果func1中使用了this指针,那就

肯定非法了,因为此时this指针为null

对于printf("%d\n",((TestProperty*)0)->func1);就是打印函数的地址了,这个在vc6中可以正常运行,但在vs2013会报调用函数需要传参的错误,所以就用内联汇编来

代替了,如下:

char* myword = "%d\n";__asm{mov eax, offset TestProperty::func1push eaxpush dword ptr[myword]call printfaddesp,8}

收敛自己的脾气,偶尔要刻意沉默,

aProperty) 这样的表达式会报错吗?

相关文章:

你感兴趣的文章:

标签云: