1. 程式人生 > >Computer Graphics Changes Your Life

Computer Graphics Changes Your Life

引言:近日CSDN的"C/C++語言"版的一個問題引起了我的注意:"請問虛擬函式表放在哪裡?"。我也曾經思考過這個問題,零零散散也有一定的收穫,這次正好趁這個機會把我對這一部分的理解整理一下。 首先值得宣告的是,本文的編譯環境是VS2002+WinXP。C++標準並沒有對虛擬函式的實現作出任何的說明,甚至都沒有提到虛擬函式的實現需要用虛表來實現,只不過主流的C++編譯器的虛擬函式機制都是通過虛表來實現的,所以用虛表來實現虛擬函式就成了"不是標準的標準"。但是這並不代表所有編譯器在實現細節上的處理都是完全一致的,它們或多或少都存在一定的個體差異。所以,本文的結論不一定適用於其他的編譯情況。

虛擬函式/虛表的基礎知識

一個類存在虛擬函式,那麼編譯器就會為這個類生成一個虛表,在虛表裡存放的是這個類所有虛擬函式的地址。當生成類物件的時候,編譯器會自動的將類物件的前四個位元組設定為虛表的地址,而這四個位元組就可以看作是一個指向虛表的指標。虛表裡依次存放的是虛擬函式的地址,每個虛擬函式的地址佔4個位元組。

編譯模組內部虛表存放的位置
如果一個模組定義了擁有虛表的類,那麼這個類的虛表存放在那裡呢?要回答這個問題,我們還是需要用匯編程式碼入手,我首先建立了一個簡單的Win32 Console Application,然後定義了一個帶虛擬函式的類,在相應的彙編程式碼中,我找到了重要的破解虛表存放位置的重要線索: CONST    SEGMENT
  
??[email protected]@[email protected]                                     ; CDerived::`vftable'
      DD FLAT:?[email protected]@@UAEXXZ
      DD FLAT:
?[email protected]@@UAEXXZ
  ; Function compile flags: 
/Odt /RTCsu /ZI
CONST    ENDS

以上的彙編程式碼給了我們這樣的資訊:
1> 虛表存放的位置應該實在模組的常量段中;
2> 這個類有兩個虛擬函式,它們分別是
[email protected]
@@UAEXXZ和[email protected]@@UAEXXZ。

外部模組虛表存放的位置
當一個模組匯出了一個帶虛表的類,而另外一個模組又使用了這個匯出類,這時候情況又是什麼樣的呢?這裡存在兩種很自然的處理方式:
1。維護一份虛表。虛表放在定義匯出類的那個模組,任何使用這個匯出類的其他模組都要通過這個模組來使用匯出類。
2。維護多份虛表。這時候每一個使用匯出類的模組都會有一份虛表的拷貝。
VS2002是使用那一種情況呢?在假設存在多份虛表的前提下,我們可以使用這樣的策略來判斷VS2002使用那種方式:
1。在類定義模組中建立一個類物件,並在另外一個模組中使用這個類物件。在類定義模組中建立類物件保證編譯器用類定義模組中的虛表來初始化類物件。
2。在模組(非類定義模組)中建立並類物件並使用它。這樣就保證編譯器會用模組中的虛表來初始化類物件。
3。分別獲取兩種情況下兩個類物件的虛表指標。如果它們的值相等,就說明只存在一份虛表;如果它們的值不等,就說明存在多份虛表。
4。如果兩個虛表指標的值相等,則虛表來自於兩個模組中的一個模組,判斷這個虛表來自於那個模組。

應用上面的策略,我們首先建立一個Win32 DLL工程匯出一個帶虛表的類,再建立一個Win32 Consle Application使用這個匯出類。在Win32 Consle Application的主函式中,我寫了以下的程式碼:     CDllInDepth* pObjInAnotherDLL = createObject();
    
int vTableAdress = *reinterpret_cast<int*>(pObjInAnotherDLL);
    
int vFuncAddress = *reinterpret_cast<int*>(vTableAdress);
    pObjInAnotherDLL->dumpMe();

    CDllInDepth* pObjInMyApp = 
new CDllInDepth;
    
int vTableAdress2 = *reinterpret_cast<int*>(pObjInMyApp);
    
int vFuncAddress2 = *reinterpret_cast<int*>(vTableAdress);
    pObjInMyApp->dumpMe();

對這段程式碼做如下的解釋:
1。createObject()是DLL匯出了一個全域性函式。這個全域性函式實現的功能就是生成一個類物件並將類物件的地址傳出。這樣做的目的就是為了在類定義模組中生成一個類物件。
2。獲得虛表指標和虛擬函式的程式碼可以這樣分析:由於虛表指標存放在類物件的前4個位元組中,我們首先需要將類物件的首地址轉化成int型指標,並通過這個int型指標獲得前4個位元組的內容,這個內容就是虛表的地址。接著我們將這個虛表的地址再轉化成int型指標,並通過這個int型指標獲得虛表的前4個位元組的內容,這個內容就是虛表的第一項的值,也就是一個虛擬函式的地址。

通過除錯,我們得出這樣的結果: vTableAdress  =0x1001401C        vFuncAddress  =0x1001103C
vTableAdress2 
=0x1001401C        vFuncAddress2 =0x1001103C
比較vTableAdress和vTableAdress2的值我們發現它們的值是完全一樣的,這就說明我們的假設是不正確的,這裡是存在一份虛表。那最後的一個問題就是這個虛表是來自於那個模組呢?這個答案我們需要通過比較虛表的地址以及模組所佔的記憶體空間來解答。在除錯狀態下,開啟"模組"視窗,我們就可以找到模組的地址:   TestApp.exe            00400000-00417000
  DllInDepth.dll        
10000000-10019000

其中的DllInDepth.dll模組就是定義匯出類的模組,而TestApp.exe就是使用這個類的模組。通過比較不難發現,虛表的地址落在DllInDepth.dll的地址範圍內,這就說明了虛表來在於類定義的模組。

到了現在,關於虛表存放的問題基本上都得到了圓滿的解決,但是我又有了一個新的問題:為什麼會是這樣的情況呢?我想,大概應該是這樣的原因吧:類物件虛表指標的初始化應該發生在建構函式被呼叫的時候,更具體的說應該實在進入到建構函式"{"之前,這個時機就是通常所說的建構函式"初始化列表"被執行的時候。由於建構函式是在類定義模組中執行的,當然虛表也應該是類定義模組的虛表,對於其他的模組而言就是匯入函式的呼叫,這樣就沒有必要維護多份虛表了。

後記

雖然本文的主要內容是討論虛表的位置,實際上本文涉及到DLL匯出類的內容。在論壇上也經常看到一些網友對DLL匯出類的內容感到迷惑。相對於簡單的函式和資料,類的構成將顯得比較複雜,類宣告中可以包含任意型別的資料,成員函式,虛擬函式,靜態函式,我們就不禁迷惑這些東西是以什麼樣的方式匯出並讓其他的模組使用的?對於這個問題,我不禁想到了一個很有名的縮寫"KISS(Keep It Simple, Stupid)"。這是一個很有用的思維方式,我們就不妨嘗試使用這種思維方法從簡單的出發點開始思考。對於DLL來說,作為一個模組,使用者感興趣的無非是程式碼和資料:
  •     對於程式碼來說,DLL是以函式符號的形式匯出的。
  •     對於資料來說,DLL是以資料符號的形式匯出的。

在對C++類的結構(或者說模型)進行深入分析的基礎上,我們知道,對於C++類,它既有程式碼,也有資料:

  •    程式碼是以類的成員函式,類的虛擬函式和類的靜態函式的形式存在的;
  •    資料包含類的靜態成員變數和類的虛表。

由此可見,從本質上來說,DLL匯出類的情況就是匯出函式和資料,並沒有什麼神祕的。如果我們再加上類的特殊性的分析,問題的答案就清晰了:

  1. 對於成員函式,虛擬函式,靜態函式和靜態資料,他們都處於類的作用域內,所以他們匯出的函式符號中應該包含類的資訊。
  2. 對於成員函式和虛擬函式,他們的第一個引數應該是指向類物件的指標,並且他們以"__thiscall"的呼叫習慣(calling convention)呼叫。
  3. 對於類的靜態函式和靜態資料,DLL按照全域性函式和全域性資料的處理方式一樣處理他們。
  4. 虛表是以常量的形式匯出的。

^_^,DLL匯出類的情況盡是如此的簡單,沒有想到吧,不過"情況就是這樣的"。

參考文獻
1.提到C++物件模型,就不得不提這本書:《深度探索C++物件模型》。對這本書的評價我就不羅嗦了,反正是隻要涉及到C++物件模型的問題,很多人告訴你去看這本書就好了。相對於很多人這本書幾乎痴迷的崇拜,我保留我自己一點小小的看法。C++物件模型的細節太依賴於C++編譯器,各個不同廠商的編譯器之間,甚至是同一廠商不同版本編譯器之間,都可能存在這樣或者那樣的差別。對於不同的編譯器,我們還是要"就事論事",通過自己的實踐來獲得某個編譯器下的"第一手資料",而不能100%迷信書中的說法。
2.無意中發現一篇網友的BLOG文章,內容正好也是關於DLL中匯出C++類,我發現寫的比我的詳細,對這個問題特別感興趣的朋友可以看看這篇文章:
   

歷史記錄
01/28/2007   v1.0
原文的第一版
05/10/2007  v1.1
新增:在後記中添加了對DLL匯出類的內容的分析

相關推薦

Computer Graphics Changes Your Life

引言:近日CSDN的"C/C++語言"版的一個問題引起了我的注意:"請問虛擬函式表放在哪裡?"。我也曾經思考過這個問題,零零散散也有一定的收穫,這次正好趁這個機會把我對這一部分的理解整理一下。 首先值得宣告的是,本文的編譯環境是VS2002+WinXP。C++標準並沒有對虛擬

2018年9-12月份雅思口語題庫素材(原創)describe the first cellphone of yours that brought changes to your life

When I was a child in the primary school, I always used my parents’ phone. After studying in the high school, I hoped to own a phone bel

【簡簡單單】———————I like computer,programme,music.Be sure that you have never had any regrets in your life which only lasts for a few

簡簡單單 ———————I like computer,programme,music.Be sure that you have never had any regrets in your life whic...

How to user your life

“How we spend our days is ,of course, how we spend our lives.”——Annie Dillard ,The Wirting Life In the summer of 1997, NASA’s Pathfinder space

People in your life 你生活中的人們

People come into your life for a reason, a season, or a lifetime. When you figure out which one it is, you will know what to do for each p

Computer Graphics】平面表示式及相關計算

內容 引數化表示式 求平面法向量 求點到平面的距離 求直線與平面交點 求三個平面斜交 1.  引數化表示式 已知一個三維點 P 與法向量 N,設過點 P 且與 N 垂直的平面為點 Q 的合集,那麼 Q 滿足:   除此之外,平面方程還有一種常用的表達方

Computer Graphics Principles And Practice

1 Introduction 2 Introduction to 2D Graphics Using WPF 3 An Ancient Renderer Made Modern 4 A 2D Graphics Test Bed 5 An Introduction to Human Visual Per

Love Your Life

However mean your life is,meet it and live it ;do not shun it and call it hardnames.It is not so bad as you suppose.It looks poorest when you are ri

How AI could compose a personalized soundtrack to your life Pierre Barreau

Meet AIVA, an artificial intelligence that has been trained in the art of music composition by reading more than 30,000 of history's greatest scores. In a

Risk, failure, and living your life: The economics of being an early

At the end of each weekday, doctoral student Ryan Hill travels from his office in the MIT Department of Economics to his residence at the west end of campu

How algorithms are controlling your life

Algorithms are a black box. We can see them at work in the world. We know they're shaping outcomes all around us. But most of us have no idea what they are

Ask HN: Did reading HN bring anything valuable into your life?

I'm trying to figure out my motivations behind specific online habits. One of them is reading HN.I'm curious if reading HN bring anything valuable into you

Ask HN: What scripts/cronjobs you have made that made your life generally easier

I used to back up my friend's website over FTP to a git repo. He often would break something and have no way to know what broke or how to fix it.I frequent

How to Decide What to Do With Your Life

Stop Doing This to YourselfWhat’s your purpose in life?What’s your passion?These questions send cortisol grenades throughout your body when you think about

Top skills for Alexa: 6 tips for your Amazon Echo that will simplify your life

Here are 21 commands that even seasoned Echo users may not know. Many of them are useful, some are fun, and others give the illusion that Alexa is as cogni

How a gaming chip could someday save your life

Jensen Huang, the billionaire CEO of Nvidia, has made a fortune by supplying the hardware used for artificial-intelligence algorithms. He's now betting tha

10 apps that can make your life way easier, all of which are on sale

Apps make the world go'round. Whether you're on the hunt for an app that can help you create a business plan or a platform that affords you unlimited acces

Digital immortality: How your life's data means a version of you could live forever

Hossein Rahnama knows a CEO of a major financial company who wants to live on after he's dead, and Rahnama thinks he can help him do it. Rahnama is creatin

Apple Wants to Save Your Life

Apple’s yearly iPhone product unveiling, the Super Bowl of tech events, wasn’t a snoozer. But on almost all points, the outcome was preordained.A torrent o

12 Computer Science Curriculum; your school should too.

What do you need to achieve your goals?Once you have your goals identified, you can now pursue the process by which you will achieve those goals. Just as w