天下

记录修行的印记

[转]深入解析c++静态联编和类的成员函数调用

只要学了C++的人,肯定知道静态联编和动态联编,如果你不知道,ok那你学习 之路还长。简单的静态联编的东西就不说了。先看下面程序。

#include <iostream>
using namespace std;
class AA{
 
public:
     
void result()
       {
            std::cout 
<< "Surprise?" << std::endl;
       };
 };
int main()
{
    AA 
*= NULL; //注意这里是NULL
    p
->result();
    ((AA
*)0)->result();
    system(
"Pause");
    
return 0;
}


上面程序运行会报错吗?
——————————————————————

如果你说运行一切正常并知道原因,ok。那就别往下看了,时间就是金钱。

确实,这个运行正常并输出  Surprise? 不信?你copy过去运行下试试。为啥啊。明明指针p的值是NULL,而你使用NULL指针去调用成员函数,明明会报内存错误的瑟。书上不是说了不能使用 NULL指针吗?嘿嘿,没错,确实不能使用NULL指针,但是这里,程序根本就没有用指针p的值,而是仅仅用到了它的类型做静态束定而已。

要解此题首先要明确两个问题。

1、静态联编的原理;2、成员函数的代码在运行期只有一份拷贝。

静态联编简单的说就是在编译期就已经确定了要调用哪个函数了,这里的result()就是。同时要知道,类的成员函数在运行期只有一份拷贝在内存,不管类的实例有多少个,成员函数始终只有一份代码在内存,因此只要知道类的指针的类型之后,就可以定位到函数的入口地址,根本不关心该指针指向的是一个什么东西。成员函数和成员变量不一样,非静态成员变量是跟随类的实例走的。

ok,明白上面两个问题之后,这个事情就好解决了。直接上汇编吧。

汇编如下:

AA *p = NULL;
00411ACE  mov         dword ptr [p],0
p->result();
00411AD5  mov         ecx,dword ptr [p]
00411AD8  call          AA::result (41105Ah)

清楚了吧。在执行p->result()的时候只是把p的值移动到了一个暂存器里面,但是并没有用到这个值,后面就直接调用AA::result函数了,0x41105A正是该函数的入口地址。

ok,好了。不仅可以向以上说的去访问成员函数,甚至再过分一点((A*)0)->result();这样都可以。你再火一点把那个0换成任意一个地址都可以正确调用到那个函数,因为编译器在静态束定的时候只关心那个指针的类型。当然了,不可这样去访问类的成员变量,因为成员变量是在对象的内存布局里面的。

值得说一点的是,如果你在result函数里面有涉及到类的成员变量的访问,那么这显然就会出错了,因为成员变量需要通过传进来的this指针(其实就可以理解成时p指针)去访问对象的内存的。然而此时p还没有指向一个有效的空间。故而出错。


posted on 2010-10-26 12:02 天下 阅读(923) 评论(8)  编辑 收藏 引用 所属分类: C/C++

评论

# re: 深入解析c++静态联编和类的成员函数调用 2010-10-26 18:26 OwnWaterloo

请教一下, "静态联编"和"动态联编"这两个术语的出处在哪?  回复  更多评论   

# re: 深入解析c++静态联编和类的成员函数调用 2010-10-26 23:46 ...

这跟C++有什么关系? 内存储存机制都是这样的。 你间接调用一个API 看看, 看看真正的API入口点是什么。

甚至再过分一点((A*)0)->result();这样都可以。你再火一点把那个0换成任意一个地址都可以正确调用到那个函数

你在函数上面加个变量看看。  回复  更多评论   

# re: 深入解析c++静态联编和类的成员函数调用 2010-10-27 09:14 天下

@OwnWaterloo
《深度探索C++对象模型》有详细的解释.
  回复  更多评论   

# re: 深入解析c++静态联编和类的成员函数调用 2010-10-27 10:08 溪流

@天下
没看出来质疑的语气吗?
不过很多大学教科书确实也都这么叫。。。  回复  更多评论   

# re: 深入解析c++静态联编和类的成员函数调用 2010-10-27 11:01 OwnWaterloo

@天下
能详细说说是哪一章节, 以及哪一版本吗?
中文版至少有3个版本, 侯捷的简体与繁体、 还有另一个人翻译的简体。
再次感谢~


@溪流
我最开始是听一个学弟在论坛上这么说, 以为是他自己造的一个词。
后来偶尔也有文章出现这样的词。
今个儿终于逮到机会问问。
是哪本大学教科书啊?  回复  更多评论   

# re: 深入解析c++静态联编和类的成员函数调用 2010-10-27 16:27 天下

@OwnWaterloo
@OwnWaterloo
@溪流

大学里教过,很多书里面也有讲.
但是,
不好意思,文章是转的.,可能记错了,不记得是哪本书里讲过.
  回复  更多评论   

# re: [转]深入解析c++静态联编和类的成员函数调用[未登录] 2010-10-27 23:25 OwnWaterloo

@天下
I see. 谢谢~  回复  更多评论   

# re: [转]深入解析c++静态联编和类的成员函数调用 2010-10-28 02:16 溪流

@OwnWaterloo
我手上有一本科学出版社《Visual C++ 程序设计基础》,大一时候一门课用的  回复  更多评论   


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


<2010年10月>
262728293012
3456789
10111213141516
17181920212223
24252627282930
31123456

导航

统计

常用链接

留言簿(4)

随笔分类(378)

随笔档案(329)

链接

最新随笔

搜索

最新评论