青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

統(tǒng)計(jì)

  • 隨筆 - 50
  • 文章 - 42
  • 評(píng)論 - 147
  • 引用 - 0

留言簿(6)

隨筆分類

文章分類

Link

搜索

  •  

積分與排名

  • 積分 - 167079
  • 排名 - 159

最新評(píng)論

閱讀排行榜

評(píng)論排行榜

MSVC++ 對(duì)象內(nèi)存模型深入解析與具體應(yīng)用 (二)

MSVC++ 對(duì)象內(nèi)存模型深入解析與具體應(yīng)用

前言:本文之所以強(qiáng)調(diào)MSVC, 旨在提醒讀者在不同平臺(tái)和解釋器下內(nèi)存布局和實(shí)現(xiàn)上存在差異,但編程思想通用,文中內(nèi)容大多來(lái)自筆者實(shí)際工作經(jīng)驗(yàn)和網(wǎng)上搜集,力求正確,但水平有限,如有不當(dāng)之處,敬請(qǐng)指出

面向?qū)ο螅罕疚拿嫦蛴幸欢?/span>C/C++基礎(chǔ),并且可以讀懂部分匯編的讀者

版權(quán):歡迎轉(zhuǎn)載,但請(qǐng)注明出處http://m.shnenglu.com/dawnbreak/ 保留對(duì)本文的一切權(quán)力

目錄
1. C++基本類型與結(jié)構(gòu)體內(nèi)存布局
                Key words: class,  struct, memory alignment

2.虛表, 多態(tài)與動(dòng)態(tài)綁定

                Key words: Virtual Table, polymiorphism

3.對(duì)象池

                Key words: object pool , reload, new ,delete

4.內(nèi)存泄漏檢測(cè)

                Key words: memory leak detect

5.智能指針

                Key words: smart pointer

6.   編譯期類型約束
   
                Key words: compile-time ,type-constraint


 Appendix 1: C++堆棧祥解



第二章  虛表, 多態(tài)與動(dòng)態(tài)綁定

Key words: Virtual Table, polymiorphism

1.虛表-Virtual Table 多態(tài)-polymiorphism

       虛函數(shù)表由虛函數(shù)的地址組成,表中函數(shù)地址的順序和它們第一次出現(xiàn)的順序(即在類定義的順序)一致。若有重載的函數(shù),則替換掉基類函數(shù)的地址,事實(shí)上你可以簡(jiǎn)單的將虛表定義理解如下:

        Int* virtualTable[size]//普通的指針數(shù)組而已

        
多數(shù)情形下,MSVC的類按如下格局分布:

?           指向虛函數(shù)表的指針(_vtable__vftable_),不過(guò)它只在類包括虛函數(shù),以及不能從基類復(fù)用合適的函數(shù)表時(shí)才會(huì)被添加。

?           基類。

?             函數(shù)成員。

請(qǐng)看如下例子:


#include "stdafx.h"
#include 
"assert.h"
#include 
"iostream"
using namespace std;
class A
{
public:
  
int b1;
  
static int b3;
  
int b2;
public:

  
virtual void A_virt1()
  
{
      std::cout
<<"  call of first A's vf"<<std::endl;
  }


  
virtual void A_virt2()
  
{
      std::cout
<<"  call of second A's vf"<<std::endl;
  }


}
;
int A::b3=100;
//#pragma pack(1)
class B:public A
{
    
int a1;
    
char b1;
    
float c1;
  
virtual void A_virt2()
  
{
      std::cout
<<"  call of second B's vf"<<std::endl;
  }
    
  
virtual void B_virt1()
  
{
        std::cout
<<"  call of second B's vf1"<<std::endl;
  }

    
virtual void B_virt2()
  
{
        std::cout
<<"  call of second B's vf2"<<std::endl;
  }

    
void getsome();
}
;
void B::getsome()
{
    
int a=1;
}


class D:public A
{
}
;

class C:public B,public D
{
  
virtual void B_virt1()
  
{
        std::cout
<<"  call of first C's vf"<<std::endl;
  }

}
;
int _tmain(int argc, _TCHAR* argv[])
{
    typedef 
void(*pfunc)();
    cout
<<"test the class memory layout-virtual table"<<endl;
    C cc;
    (pfunc(((
int**)(&cc))[0][0]))();
    (pfunc(((
int**)(&cc))[0][1]))();
    (pfunc(((
int**)(&cc))[0][2]))();
    (pfunc(((
int**)(&cc))[0][3]))();

    system(
"pause");
    
return 0;
}

程序輸出結(jié)果:


以下是各個(gè)類在內(nèi)存中的布局圖

class A size(12):
 
+---
 
0 | {vfptr}
 
4 | b1
 
8 | b2
 
+---
A::$vftable@:
 
| &A_meta
 
|  0
 
0 | &A::A_virt1
 
1 | &A::A_virt2
A::A_virt1 
this adjustor: 0
A::A_virt2 
this adjustor: 0
class B size(24):
 
+---
 
| +--- (base class A)
 
0 | | {vfptr}
 
4 | | b1
 
8 | | b2
 
| +---
12 | a1
16 | b1
   
| <alignment member> (size=3)
20 | c1
 
+---
B::$vftable@:
 
| &B_meta
 
|  0
 
0 | &A::A_virt1
 
1 | &B::A_virt2
 
2 | &B::B_virt1
 
3 | &B::B_virt2
B::A_virt2 
this adjustor: 0
B::B_virt1 
this adjustor: 0
B::B_virt2 
this adjustor: 0
class D size(12):
 
+---
 
| +--- (base class A)
 
0 | | {vfptr}
 
4 | | b1
 
8 | | b2
 
| +---
 
+---
D::$vftable@:
 
| &D_meta
 
|  0
 
0 | &A::A_virt1
 
1 | &A::A_virt2
class C size(36):
 
+---
 
| +--- (base class B)
 
| | +--- (base class A)
 
0 | | | {vfptr}
 
4 | | | b1
 
8 | | | b2
 
| | +---
12 | | a1
16 | | b1
   
| | <alignment member> (size=3)
20 | | c1
 
| +---
 
| +--- (base class D)
 
| | +--- (base class A)
24 | | | {vfptr}
28 | | | b1
32 | | | b2
 
| | +---
 
| +---
 
+---
C::$vftable@B@:
 
| &C_meta
 
|  0
 
0 | &A::A_virt1
 
1 | &B::A_virt2
 
2 | &C::B_virt1
 
3 | &B::B_virt2
C::$vftable@D@:
 
| -24
 
0 | &A::A_virt1
 
1 | &A::A_virt2
C::B_virt1 
this adjustor: 0

為了調(diào)用虛函數(shù),編譯器首先需要從_vftable_取得函數(shù)地址,然后就像調(diào)用簡(jiǎn)單方法一樣(例如,傳入_this_指針作為隱含參數(shù))。例如:

          cc.A_virt2()

          ;esi = ptr [cc]

          mov eax, [esi]  ;fetch virtual table pointer

          mov ecx, esi

          call [eax+4]  ;call second virtual method

          ;cc->B_virt1()

          ;edi = pC

          lea edi, [esi+8] ;adjust this pointer

          mov eax, [edi]   ;fetch virtual table pointer

          mov ecx, edi

call [eax]       ;call first virtual method


注意到上面class A的內(nèi)存布局圖,首先是VT指針,然后是成員變量b1,b2, 而對(duì)于靜態(tài)成員b3并沒(méi)有體現(xiàn),事實(shí)上b是存儲(chǔ)在程序的全局靜態(tài)數(shù)據(jù)區(qū),供該類的所有實(shí)例共享,這里請(qǐng)注意在classA中虛表中虛函數(shù)出現(xiàn)的順序和位置,這一點(diǎn)很重要,接著再看classB中虛函數(shù)出現(xiàn)的順序和位置,注意到A_virt1,A_virt2在classA和classB中出現(xiàn)的順序和位置一致,而所不同的是在classB的虛表中A_virt2已經(jīng)被替換,這就是多態(tài)的關(guān)鍵所在,每一個(gè)虛函數(shù)本身其實(shí)不過(guò)是一個(gè)固定的偏移量,而真正實(shí)現(xiàn)多態(tài)的其實(shí)是在編譯器的虛函數(shù)表的替換動(dòng)作.

而對(duì)于多繼承情況要復(fù)雜一些,例如在ClassC中每一個(gè)繼承路徑中都存在一個(gè)虛表,如果在沒(méi)函數(shù)里再加入如下調(diào)用:
 (pfunc(((int**)(&cc))[6][0]))();
 (pfunc(((int**)(&cc))[6][1]))();
會(huì)輸出:
call of first A's vf
call of second A' vf
這樣一個(gè)類中同時(shí)存在兩個(gè)一抹一樣的函數(shù),那么當(dāng)你用
C cc;
cc.A_virt2()時(shí)會(huì)怎么樣呢?
你會(huì)得到以下錯(cuò)誤:
error C2385: ambiguous access of 'A_virt2'

解決辦法有兩種:
1. 調(diào)用時(shí)加入域操作符,例如:
cc.A::A_virt2();
cc.B::A_virt2( );
這種辦法最穩(wěn)妥也最清晰
2. 使用虛基類
代碼改動(dòng)如下:

。。。。。。。
class B:virtual public A
。。。。。。。
class D:virtual public A
。。。。。。。
int _tmain(int argc, _TCHAR* argv[])
{
。。。。。。。
 (pfunc(((int**)(&cc))[0][0]))();
 (pfunc(((int**)(&cc))[0][1]))();
 //(pfunc(((int**)(&cc))[0][2]))();
 //(pfunc(((int**)(&cc))[0][3]))();
 //(pfunc(((int**)(&cc))[6][0]))();
 //(pfunc(((int**)(&cc))[6][1]))();
 cc.A::A_virt2();
 cc.A_virt2();
。。。。。。。。
}

內(nèi)存布局變?yōu)椋?br>

class C size(36):
 
+---
 
| +--- (base class B)
 
0 | | {vfptr}
 
4 | | {vbptr}
 
8 | | a1
12 | | b1
   
| | <alignment member> (size=3)
16 | | c1
 
| +---
 
| +--- (base class D)
20 | | {vbptr}
 
| +---
 
+---
 
+--- (virtual base A)
24 | {vfptr}
28 | b1
32 | b2
 
+---
C::$vftable@B@:
 
| &C_meta
 
|  0
 
0 | &C::B_virt1
 
1 | &B::B_virt2
C::$vbtable@B@:
 
0 | -4
 
1 | 20 (Cd(B+4)A)
C::$vbtable@D@:
 
0 | 0
 
1 | 4 (Cd(D+0)A)
C::$vftable@A@:
 
| -24
 
0 | &A::A_virt1
 
1 | &thunk: this-=4goto B::A_virt2

 

多了一個(gè)vbtable存儲(chǔ)偏移量,第一個(gè)元素存儲(chǔ)vbtable與該類的偏移量,第二個(gè)元素存儲(chǔ)vbtable與公共基類的偏移量,而且注意到,vftable@A 的第二個(gè)虛函數(shù)被定向到B:A_virt2
這樣問(wèn)題解決了,但是你會(huì)得到一個(gè)警告:
Warning 1 warning C4250: 'C' : inherits 'B::B::A_virt2' via dominance
顯示繼承了 'B::B::A_virt2‘ ,也就是說(shuō)你在調(diào)用
cc.A_virt2時(shí),默認(rèn)直接去調(diào)用B::A_virt2,這可能并不是你所期望的,所以使用時(shí)需要慎重


2 . 動(dòng)態(tài)邦定與靜態(tài)邦定
邦定是指一個(gè)計(jì)算機(jī)程序自身彼此關(guān)聯(lián)的過(guò)程。按照邦定所進(jìn)行的階段不同,可分為兩種不同的邦定方法:靜態(tài)邦定和動(dòng)態(tài)邦定。
靜態(tài)邦定
靜態(tài)邦定是指邦定工作出現(xiàn)在編譯連接階段,這種邦定又稱早期邦定,因?yàn)檫@種邦定過(guò)程是在程序開始運(yùn)行之前完成的。
在編譯時(shí)所進(jìn)行的這種邦定又稱靜態(tài)束定。在編譯時(shí)就解決了程序中的操作調(diào)用與執(zhí)行該操作代碼間的關(guān)系,確定這種關(guān)系又稱為束定,在編譯時(shí)束定又稱靜態(tài)束定。
 1class AA
 2{
 3public:
 4   void test()
 5   {
 6      cout<<"I am class AA!"<<endl;
 7   }

 8}
;
 9class BB
10{
11public:
12   void test()
13   {
14      cout<<"I am class BB!"<<endl;
15   }

16}
;
17int _tmain(int argc, _TCHAR* argv[])
18{
19    AA *A=(AA *)(new BB);
20    A->test();
21}

讀者可以想一下以上例子的結(jié)果,如果說(shuō)是I am class BB!

C++沒(méi)有你想得那么職能,C++調(diào)用函數(shù)不過(guò)是指針偏移,而一般成員函數(shù)代碼是在數(shù)據(jù)存儲(chǔ)區(qū)的共享代碼段,聲明了AA類的指針 A 就已經(jīng)指定了偏移的起點(diǎn)是類型AA的代碼段起點(diǎn),這一步就是所謂的動(dòng)態(tài)邦定,而調(diào)用->test();只能得到I am class AA!

也許你要說(shuō)我并沒(méi)有實(shí)例化AA怎么會(huì)有那一段代碼呢,請(qǐng)注意代碼生成和實(shí)例化是完全不同的兩個(gè)階段,編譯在編譯時(shí)發(fā)現(xiàn)你調(diào)用了AA::test(); 那么就會(huì)載入相應(yīng)的symbol,程序啟動(dòng)時(shí)就會(huì)載入相應(yīng)代碼段。

也許你還要說(shuō)沒(méi)有用繼承的關(guān)系,那么你可以自己試驗(yàn)一下使BB繼承自AA 結(jié)果還是一樣的

想要實(shí)現(xiàn)想要的結(jié)果唯一的方法就是使用虛函數(shù)來(lái)實(shí)現(xiàn)動(dòng)態(tài)邦定;

 

posted on 2009-03-11 14:25 pear_li 閱讀(2074) 評(píng)論(4)  編輯 收藏 引用 所屬分類: C++

評(píng)論

# re: MSVC++ 對(duì)象內(nèi)存模型深入解析與具體應(yīng)用 (二) 2009-03-11 15:07 電腦學(xué)習(xí)步步高

剛發(fā)現(xiàn)的好玩的網(wǎng)站想玩來(lái)http://my.diannaobbg.cn/invite.php?u=1&c=be7fce657cf06905
http://www.diannaobbg.cn

# re: MSVC++ 對(duì)象內(nèi)存模型深入解析與具體應(yīng)用 (二) 2009-03-12 12:49 夢(mèng)在天涯

你可以研究下對(duì)象與對(duì)象的類型信息怎么聯(lián)系起來(lái)的,就是當(dāng)調(diào)用dynamic_cast的時(shí)候?yàn)槭裁茨軌蛘_的識(shí)別對(duì)象的類型!

# re: MSVC++ 對(duì)象內(nèi)存模型深入解析與具體應(yīng)用 (二) 2009-03-12 12:53 夢(mèng)在天涯

加油!

# re: MSVC++ 對(duì)象內(nèi)存模型深入解析與具體應(yīng)用 (二) 2012-09-07 11:02 劉偉

如果把內(nèi)存布局畫成圖就更好了,像《Inside the C++ Object Model》那樣。感謝樓主的文章。學(xué)習(xí)了
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            久久精品亚洲国产奇米99| 国产综合色精品一区二区三区| 亚洲青涩在线| 久久综合国产精品台湾中文娱乐网| 性欧美1819sex性高清| 国产精品99久久久久久久女警 | 在线观看不卡| 亚洲乱码国产乱码精品精天堂 | 亚洲激情综合| 一本色道久久综合亚洲精品婷婷| 一本大道久久精品懂色aⅴ| 一本久久知道综合久久| 欧美一区免费视频| 美日韩精品免费| 最新成人av在线| 亚洲欧美网站| 免费欧美在线视频| 欧美日韩免费精品| 国产在线精品一区二区中文| 亚洲国产综合在线看不卡| 亚洲一区在线观看视频| 蜜臀久久99精品久久久画质超高清| 亚洲国产精品电影在线观看| 亚洲一区二区三区四区在线观看| 久久精品国产视频| 欧美日韩综合在线免费观看| 国产一区三区三区| 国产精品99久久久久久久久久久久 | 亚洲亚洲精品在线观看| 久久久久久久性| 亚洲黄色在线看| 午夜欧美精品| 欧美日韩精品免费在线观看视频| 激情丁香综合| 欧美在线精品一区| 亚洲精品综合久久中文字幕| 久久国产夜色精品鲁鲁99| 欧美日韩免费看| 91久久亚洲| 欧美91大片| 久久激情网站| 国产午夜精品久久久| 宅男噜噜噜66一区二区66| 欧美二区乱c少妇| 欧美在线视频免费播放| 国产精品外国| 亚洲欧美日韩电影| 99re66热这里只有精品4| 美日韩免费视频| 国产一区欧美日韩| 久久精品国产成人| 亚洲性感激情| 国产精品久久久久av免费| 日韩一本二本av| 亚洲激情第一页| 免费观看国产成人| 亚洲国产综合在线看不卡| 免费成人黄色片| 久久久久久欧美| 伊人春色精品| 欧美黑人多人双交| 欧美a级一区| 亚洲看片免费| 亚洲靠逼com| 国产精品成人v| 亚洲欧美日本日韩| 午夜精品国产| 亚洲成色777777女色窝| 欧美电影打屁股sp| 欧美黄色影院| 亚洲综合色激情五月| 亚洲在线视频网站| 国产欧美一区二区三区视频| 久久精品国产久精国产一老狼 | 一区二区三区在线高清| 老司机一区二区三区| 久久亚洲精品欧美| 日韩小视频在线观看专区| 在线午夜精品| 国产视频久久| 欧美黄色免费网站| 欧美性视频网站| 久久青草欧美一区二区三区| 欧美h视频在线| 亚洲欧美视频一区二区三区| 欧美一二三区精品| 美女视频黄免费的久久| 麻豆精品视频在线观看| 日韩午夜免费视频| 亚洲午夜精品国产| 一区二区视频欧美| 亚洲美女区一区| 狠狠综合久久| 99成人精品| 亚洲第一成人在线| 一区二区三区蜜桃网| 激情av一区| 一区二区三区欧美激情| 黄色在线成人| 亚洲一区二区免费看| 亚洲电影免费在线| 一区二区三区日韩精品视频| 国产亚洲视频在线观看| 亚洲国产日韩欧美一区二区三区| 国产精品久久久久久妇女6080| 欧美ab在线视频| 国产精品日本| 亚洲精品一线二线三线无人区| 国产视频亚洲| 在线视频你懂得一区| 亚洲国产精品悠悠久久琪琪| 亚洲综合国产激情另类一区| 日韩视频在线一区二区三区| 久久精品国产一区二区三区免费看 | 午夜欧美视频| 亚洲视频 欧洲视频| 久久天天躁狠狠躁夜夜av| 香蕉久久夜色精品| 欧美极品在线观看| 免费在线一区二区| 国产亚洲毛片在线| 亚洲一区二区三区国产| 一本色道久久综合狠狠躁篇怎么玩 | 国产精品女主播一区二区三区| 久久国产精品一区二区| 欧美久久婷婷综合色| 久久精品麻豆| 欧美日韩亚洲高清一区二区| 久久久夜精品| 国产欧美va欧美不卡在线| 一区二区高清视频在线观看| 99视频超级精品| 最新国产精品拍自在线播放| 久久夜色精品| 久久精品亚洲一区二区| 国产欧美一区二区三区沐欲| 亚洲一区二区三区色| 欧美一级视频一区二区| 国产精品你懂的在线欣赏| 在线视频一区二区| 亚洲女同同性videoxma| 国产精品海角社区在线观看| 宅男噜噜噜66国产日韩在线观看| 一区二区三区视频免费在线观看| 欧美美女视频| 一本色道久久综合亚洲二区三区| 亚洲一品av免费观看| 狠狠色丁香婷婷综合| 亚洲欧美日韩一区二区三区在线| 亚洲伊人久久综合| 国产精品久久久久久户外露出| 亚洲视频axxx| 欧美一级免费视频| 国产综合久久久久影院| 久久久五月天| 91久久精品一区二区三区| 在线一区二区三区做爰视频网站| 欧美日韩国产精品一卡| 亚洲一区二区三区四区五区黄| 久久精品亚洲一区二区三区浴池| 一区免费在线| 欧美日韩免费在线| 亚洲欧美文学| 亚洲电影免费观看高清| 亚洲午夜电影网| 国产综合婷婷| 欧美日韩国产一区二区三区地区| 亚洲综合视频1区| 亚洲第一主播视频| 欧美一区二区三区在线| 亚洲国产电影| 国产精品高清网站| 久久久噜噜噜久噜久久| 在线一区日本视频| 久久嫩草精品久久久精品一| 99国产精品| 国模 一区 二区 三区| 欧美电影免费| 久久本道综合色狠狠五月| 亚洲人体一区| 久久五月激情| 亚洲欧美乱综合| 日韩视频中文字幕| 精品9999| 国产欧美一级| 欧美日韩精品一区视频 | 亚洲私人影院| 欧美电影免费观看高清| 香蕉久久夜色精品| 亚洲视频一区| 日韩小视频在线观看专区| 黄色国产精品| 国产精品老牛| 欧美日韩精品免费观看| 久久亚洲国产精品日日av夜夜| 亚洲欧美经典视频| 在线亚洲一区观看| 99国产精品国产精品毛片| 亚洲福利免费| 欧美电影在线免费观看网站|