__cxa_pure_virtual報錯(g++編譯虛擬函式時)

小菜碟子發表於2024-03-30

g++編譯os的memory'時不知道為什麼報錯。嘗試了很多方法(也可能搜錯了)

可以確定是純虛擬函式出現了問題

複習一下虛擬函式的子類構造和析構的過程吧(一年過去了)

允許派生類呼叫父類的同名函式而實現不同的功能,也叫動態聯編。

底層原理:虛擬函式表+虛擬函式表指標。每一個類都會對應一個虛擬函式表,一個存放虛擬函式地址的虛擬函式表,並建立虛擬函式指標(vptr)來指向表。

虛擬函式和純虛擬函式的區別
純虛擬函式和虛擬函式都可以在子類中被重寫,他們的區別是:
1.純虛擬函式只有定義,沒有實現,而虛擬函式有定義,也有實現的程式碼。純虛擬函式語法:virtual void print() = 0;
2.包含純虛擬函式的類不能定義其物件,而包含虛擬函式的則可以。
所以,純虛擬函式的作用就是在基類中定義這樣的介面但是又不想去實現,所以就只好設定純虛擬函式,因為只有這樣才能編譯透過。
純虛擬函式(pure virtual) :C++中包含純虛擬函式的類,被稱為是“抽象類”。抽象類不能使用new出物件,只有實現了這個純虛擬函式的子類才能new出物件。

虛擬函式指標的初始化過程
虛擬函式表的建立和虛擬函式指標的初始化都是在建構函式中進行的。當編譯器發現基類當中有虛擬函式存在時,就會為每個含有虛擬函式的類建立一個虛擬函式表(vtable),該表是一個一維陣列,存放的是虛擬函式的地址,子類中如果沒有虛擬函式也會從基類中繼承虛擬函式表,虛表建立之後還會建立一個虛擬函式指標來指向虛表,即(vptr)。

當基類的解構函式定義為虛擬函式的時候,子類可以利用自己的解構函式來呼叫基類的解構函式,從而達到整個類的完全析構。

第一步:構造最頂層的基類部分
a、讓例項指向基類的虛擬函式表
b、構造基類例項成員變數
c、執行基類建構函式
第二步:構造派生部分(遞迴的)
a、讓例項指向派生類的虛擬函式表
b、構造派生類例項成員變數
c、執行派生類建構函式
析構時則是按相反的順序,就像這樣:
第一步:析構派生部分(遞迴的)
a、(例項已經指向派生類的虛擬函式表)
b、執行派生類解構函式
c、析構派生類例項成員變數
第二步:析構基類部分(遞迴的)
a、讓例項指向基類的虛擬函式表
b、執行基類解構函式
c、析構基類例項成員變數

根據上面的流程,建構函式和解構函式執行過程中,都有一段時間物件的虛擬函式指標指向基類虛擬函式表,如果在構造或者析構沒有完成的時候呼叫了該物件的虛擬函式,則是呼叫了基類的純虛擬函式。這種情況一般發生在多執行緒呼叫,構造或析構在一個執行緒,虛擬函式呼叫在另一個執行緒。

如果父類的函式不是純虛擬函式,而是有實現的虛擬函式,則是呼叫父類的虛擬函式,不會crash

所以我懷疑是多執行緒的問題(但是我程式碼裡沒有多執行緒啊)https://gitee.com/saucerdish(程式碼可以看這裡os)


我懷疑會不會是不能用純虛類做全域性變數呢,派生類做全域性變數試試,發現也不行

讓我們找找出錯函式吧,沒有emmm

看看.rodata段呢

停下來啊啊啊啊在這

後來我覺得真的只是沒定義呢

試試extern一下這個東西吧

行吧,好像可以了

相關文章