C++面向?qū)ο竽嫦蚬P記-創(chuàng)新互聯(lián)

筆記參考自黃色那本C++逆向揭秘

成都創(chuàng)新互聯(lián)公司-專業(yè)網(wǎng)站定制、快速模板網(wǎng)站建設、高性價比長豐網(wǎng)站開發(fā)、企業(yè)建站全套包干低至880元,成熟完善的模板庫,直接使用。一站式長豐網(wǎng)站制作公司更省心,省錢,快速模板網(wǎng)站建設找我們,業(yè)務覆蓋長豐地區(qū)。費用合理售后完善,十載實體公司更值得信賴。
對象的識別 所有的類都有構造函數(shù)嗎
  1. 情況一:編譯器會為類內(nèi)有虛函數(shù),父類有虛函數(shù),或者本類中的對象成員有虛函數(shù)的情況下,編譯器會添加默認的構造函數(shù),用于完成虛表的初始化工作。
  2. 情況二:編譯器會為父類或者本類中定義的成員對象帶有構造函數(shù)時。派生類的構造順序是先構造父類再構造自身,需要添加默認的構造函數(shù)調(diào)用父類的構造函數(shù)。
構造函數(shù)的識別
  1. 該函數(shù)的調(diào)用是某對象在作用域內(nèi)的第一次成員函數(shù)的調(diào)用,通過this指針判斷是哪個對象的成員函數(shù)。
  2. 使用thiscall調(diào)用方式,使用ecx傳遞this指針
  3. 返回值為this指針,與傳入的第一個參數(shù)相同。
析構函數(shù)的識別
  1. 該函數(shù)的調(diào)用時某對象在作用域內(nèi)的最后一次成員函數(shù)調(diào)用,通過this指針來分辨是那個對象的成員函數(shù)。
  2. 使用thiscal調(diào)用方式,使用ecx寄存器來傳遞this指針。
  3. 沒有返回值。也沒有參數(shù)。
全局構造函數(shù)和全局析構函數(shù)的調(diào)用時機

1._cinit()函數(shù)的第二個_initterm()函數(shù)內(nèi)完成,在_initterm()中。會先執(zhí)行__onexitinit()函數(shù)初始化函數(shù)指針數(shù)組。在執(zhí)行每個全局對象構造代理函數(shù)時都會先執(zhí)行對象的構造函數(shù),然后使用atexit()函數(shù)注冊析構代理函數(shù)。
2. 編譯器會為每個全局對象和靜態(tài)對象建立一個中間代理的析構函數(shù)用于傳入全局對象的this指針。(那局部對象、參數(shù)對象和返回對象呢?)

函數(shù)調(diào)用時對象是否調(diào)用拷貝構造函數(shù)

1.編譯器默認采用的是淺拷貝,即所有拷貝的對象和原對象引用的是同一資源,比如指針會簡單地復制,而不是申請新的內(nèi)存空間,將指針所指向的內(nèi)容進行拷貝然后復制。這種淺拷貝在對象退出其作用域時釋放資源可能引發(fā)錯誤,將同一份資源重復釋放。
2.函數(shù)調(diào)用時,如果以對象為參數(shù)而非對象指針或引用為參數(shù),并且返回一個對象。調(diào)用之前,棧中除了局部對象的內(nèi)存空間外,還有一份內(nèi)存空間用于保存返回對象。調(diào)用函數(shù)之后在該棧幀中生成一個對象,退出函數(shù)時,該對象會被拷貝到返回對象中,最后回到調(diào)用者的棧幀后,再將該對象拷貝到引用該對象的變量中。
3. 設置了返回對象的原因是,如果調(diào)用者的作用域某變量要引用被調(diào)用函數(shù)中的對象,而此時已經(jīng)退出該函數(shù)棧幀,即退出了該局部變量的作用域。棧中的數(shù)據(jù)(包括作為參數(shù)傳入的返回對象的地址)可能被覆蓋從而產(chǎn)生錯誤,所以需要在調(diào)用者的棧幀中用一塊內(nèi)存空間保存返回對象和臨時對象,將返回對象拷貝到臨時對象中,方便后續(xù)的引用。拷貝順序:被調(diào)用者中的對象–>返回對象–>臨時對象–>調(diào)用者中的對象。
4. 如果使用指針作為參數(shù)和返回值,函數(shù)內(nèi)就沒有對拷貝構造函數(shù)的調(diào)用。這也是一個判斷參數(shù)或返回值時對象還是對象指針的方法。

虛函數(shù)的識別
  1. 找到對象的虛函數(shù)表
  2. 利用IDA的交叉引用,找到引用虛函數(shù)表的位置(構造函數(shù)和析構函數(shù)會設置虛函數(shù)表)
  3. 根據(jù)前面的條件,判斷這些函數(shù)是否是構造函數(shù)和析構函數(shù)。
  4. 如果滿足條件,這說明這是一個虛函數(shù)。否則則可能是用戶自定義的函數(shù)指針數(shù)組。
對象的析構和釋放
  1. 如果析構函數(shù)是虛函數(shù),也會有多態(tài)行為。表現(xiàn)在匯編指令中,會發(fā)現(xiàn),調(diào)用虛表中的析構函數(shù)前,也會重復對虛表進行寫入。但是寫入順序與構造函數(shù)相反,先寫入子類自身的虛表,再寫入父類的。
  2. 析構函數(shù)釋放堆空間是兩回事。顯式調(diào)用了析構函數(shù)不一定會釋放該對象的堆空間。通過C++的放置語法,可以在已析構對象的對內(nèi)存中創(chuàng)建一個新的對象,從而節(jié)約內(nèi)存空間。如下:
    void main(int argc, char* argv[]){CPerson *pPerson = new CChinese;
    	pPerson->ShowSpeak();
    	pPerson->~CPerson();	//顯式調(diào)用析構函數(shù)
    	
    	//C++放置語法:將pPerson指向的堆內(nèi)存作為CChinese類新對象的首地址,并調(diào)用其構造函數(shù)。從而重復使用一個堆內(nèi)存。
    	pPerson = new(pPerson) CChinese();
    	delete pPerson;
    }
    在匯編指令中,會通過傳遞給析構函數(shù)的參數(shù)判斷是否需要釋放堆空間,如果不需要,則會跳過delete的調(diào)用。
判斷繼承關系的方法
  1. 在虛表的地址處利用交叉引用功能“Chart of xrefs to”得到所有直接引用這個地址的位置。
  2. 即可得到所有構造函數(shù)和析構函數(shù)。
  3. 找到每一次引用的前面最后一次寫入虛表的地方。并確定函數(shù)范圍。
  4. 構造函數(shù)中先寫入父類的虛表,再寫入子類的虛表;析構函數(shù)中則相反。

一些函數(shù)可能被編譯器內(nèi)聯(lián),從而沒有this指針的傳遞和使用。

單繼承類與多繼承類虛表指針的區(qū)別
  1. 單繼承類在類對象占用的內(nèi)存空間中,只保存一份虛表指針,對應一個虛表。構造時先構造父類函數(shù),再構造自身,析構時相反,都只調(diào)用一次父類的構造函數(shù)和析構函數(shù)。
  2. 多重繼承類保存的虛表指針的數(shù)量等于父類的個數(shù)(如果父類沒有虛函數(shù)呢?)。從子類對象轉(zhuǎn)換為父類指針時,會跳轉(zhuǎn)到對象的父類部分的首地址并賦值。構造時,按照繼承列表中的順序依次調(diào)用父類的構造函數(shù)構造對應的內(nèi)存部分,析構時先析構自身,然后按照相反順序析構父類對象部分。
  3. 對象作為成員時,類對象的內(nèi)存結構和多重繼承很相似。類中無虛函數(shù)時,整個類對象的內(nèi)存結構和多重繼承一樣。父類或成員對象存在虛函數(shù)時,通過虛表指針的位置和構造函數(shù)、析構函數(shù)中填寫虛表指針的數(shù)目及目標地址,來還原繼承貨成員關系。
    1. 假如某對象為第一個成員,且該類無虛函數(shù),那么類對象的首地址就是該成員對象的首地址,如果該成員對象有虛函數(shù),則首地址就是該成員對象的虛表指針,與多重繼承的表現(xiàn)相似
    2. 假如某對象為第一個成員,且該類有虛函數(shù),那么類對象的首地址時該類的虛表指針,然后才是該成員對象的內(nèi)存部分的首地址。
    3. 假如對象不是定義的第一個成員,則該成員對象的偏移處才是該成員對象的成員或虛表指針,此時以該成員首地址為this指針的函數(shù),即為該成員對象的成員函數(shù)(交叉引用判斷)。
虛基類和虛繼承
  1. 虛基類也稱為抽象類。
  2. 對于純虛函數(shù),由于沒有實現(xiàn)。其函數(shù)地址指向的事void __cdecl _purecall(void),該函數(shù)中會結束程序,并發(fā)出錯誤編碼信息0x19。Release版本中,編譯器會進行優(yōu)化,純虛函數(shù)將會被優(yōu)化掉。
問題
  1. 子類對象構造完成時,虛表指針已經(jīng)是子類的虛表了。為什么編譯器在析構函數(shù)中再次將虛表設置為子類的虛表?

你是否還在尋找穩(wěn)定的海外服務器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機房具備T級流量清洗系統(tǒng)配攻擊溯源,準確流量調(diào)度確保服務器高可用性,企業(yè)級服務器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧

網(wǎng)頁標題:C++面向?qū)ο竽嫦蚬P記-創(chuàng)新互聯(lián)
轉(zhuǎn)載注明:http://muchs.cn/article6/peoig.html

成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供Google靜態(tài)網(wǎng)站、企業(yè)建站、標簽優(yōu)化、虛擬主機品牌網(wǎng)站制作

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

外貿(mào)網(wǎng)站制作