RTTI機制詳解

2021-07-08 21:52:41 字數 2377 閱讀 1765

#引子

以前我們**過,rtti的訪問和虛表相關,並且rtti基本上是為了dynamic_cast<>和typeid以及異常而實現的。今天我們詳細**下異常的實現機制。

##c++abi中的rtti

通過c++程式語言的定義,我們知道型別資訊在用於以下三個目的時,可以在執行時獲得:

a. 為了支援typeid運算子

b. 為了匹配出現異常時所丟擲的異常物件

c. 為了實現dynamic_cast<>運算子

只要兩個type_info指標相同,就表明其指向的type_info相同。任何關於rtti的實現都必須滿足這個要求。

對於rtti所生成的位置,有以下描述。盡量使rtti所生成的位置數最少。對於多型型別來說,乙個相似的問題就是虛表,於是rtti應該和該型別的虛表一起生成。對於其他型別來說,它們必須在使用型別資訊的地方產生,當然目標檔案必須得包含typeid,throw或者是catch。

基本型別的型別資訊(例如,int, bool等等)將會存放在執行時庫中。特別的,對於型別"x"來說,執行時庫應該包含"x", 「x*」, 「x const *」,型別x包括void, std::nullptr_t, bool, char, unsigned char, signed char, short, unsigned short, int, unsigned int, long, unsigned long, long long, unsigned long long, float, double, long double, char16_t, char32_t等等。

注:曾經實驗室的同學一直對rtti為什麼一定要通過虛表有疑問,其實並不是rtti必須得和虛表一起生成,而是這樣做是最合適的。想一下,

(1)虛表是為了多型型別產生的,而多型型別也是需要rtti資訊的,乙個型別在乙個編譯單元中只能有乙個虛表(多型繼承時,是有多個虛表的),多個物件共享同乙個虛表。rtti同樣滿足這個性質,所以對於多型類來說,rtti和虛表生成在一起,何樂而不為呢。

(2)當然也可以生成在其他地方,只要能有一種機制能夠找到type_info型別資訊即可。c++abi中也明確規定對於多型型別來說,rtti應該和虛表一起生成。注意是應該,當然如果你沒有按照這個標準來做的話,那麼你的可執行體就會出現相容性問題,因為你和大家的不一樣嘛。

對於typeid運算子,c++abi有如下的規定,typeid運算子會產生乙個指向std::type_info結構體的引用,其中std::type_info結構體必須滿足一下介面:

namespace std;

}

在鏈結和載入之後,只能有乙個std::type_info結構體是可訪問的,並且只能夠通過c++abi定義的特定的型別名來訪問,這個型別必須是完整型別。判斷型別相等或者不想等都是通過位址比較來實現的。但時對於指標型別來說,會比較複雜,具體可以參考這裡。

由於編譯器允許虛表和rtti在不同的編譯單元中都存在,在鏈結的時候,鏈結器能夠正確判斷當前需要刪除冗餘而不是報「重定義」錯誤呢,關鍵在於虛表和rtti時存放在目標檔案中的comdat命名的section中的。這樣鏈結器就能夠根據不同的型別的內容作出不同的行為。

注:comdat塊的目的就是允許在多個目標檔案中的「重複」存在。通常如果乙個相同的符號定義在多個目標檔案中,鏈結器會報出相關錯誤。但是這樣會對一些c++語言特性造成一些問題,比如template,有可能在多個cpp檔案中例項化出同乙份符號。

關於rtti另乙個有關的內容就是dynamic_cast<>,也曾經有人和我糾結過dynamic_cast<>是不是必須得用於多型型別,答案為不是。雖然dynamic_cast<>大部分用於多型型別的指標或者引用(用於引用的話不是很妥當,如果轉換不過去不可能產生空的引用),並且在。但是dynamic_cast<>也可以在編譯時期被處理掉,並不需要rtti。例如轉換到"void *cv"就是在編譯時期做的。所以所有向空指標的dynamic_cast<>都是靜態的。

##msvc中的rtti

對於msvc來說,msvc會建立乙個指向**「complete object locator」**(即完整物件定位器)的指標並將其存放在vftable的前面。col的定義如下:

struct rtticompleteobjectlocator

;

類繼承體系描述符描述了當前類的繼承體系。它被當前類的所有cols所共享,在多重繼承下有多個虛表。

struct rtticlasshierarchydescriptor

;

##gcc中的rtti

C 中的RTTI機制詳解

前言 rtti是 runtime type information 的縮寫,意思是執行時型別資訊,它提供了執行時確定物件型別的方法。rtti並不是什麼新的東西,很早就有了這個技術,但是,在實際應用中使用的比較少而已。而我這裡就是對rtti進行總結,今天我沒有用到,並不代表這個東西沒用。學無止境,先從...

C 中的RTTI機制詳解

前言 rtti是 runtime type information 的縮寫,意思是執行時型別資訊,它提供了執行時確定物件型別的方法。rtti並不是什麼新的東西,很早就有了這個技術,但是,在實際應用中使用的比較少而已。而我這裡就是對rtti進行總結,今天我沒有用到,並不代表這個東西沒用。學無止境,先從...

RTTI實現分析

一般來說我們盡量使用虛函式來進行動態型別繫結,但是我們想使用基類物件的指標或引用執行某個派生類操作並且該類不是虛函式時,我們要動態區分類物件的型別。以下是接管型別管理的方法,實現動態型別識別的方法有三種 實現方式 在基類中定義虛函式,返回具體的型別資訊 所有的派生類都必須實現型別相關的虛函式 每個類...