CRT是指C Runtime Library,這里的意思是啟動代碼
鏈接器會指定二進(jìn)制的入口函數(shù)驳棱?
入口函數(shù)做兩件事:1 正確初始化crt豪诲;2靜態(tài) c++對象構(gòu)造函數(shù)被調(diào)用
calling convention也叫調(diào)用慣例
關(guān)于calling convention可以參考這個
一個調(diào)用慣例一般規(guī)定以下兩方面的內(nèi)容:
- 函數(shù)參數(shù)的傳遞方式万伤,是通過棧傳遞還是通過寄存器傳遞(這里我們只講解通過棧傳遞的情況)。
- 函數(shù)參數(shù)的傳遞順序俯渤,是從左到右入棧還是從右到左入棧僧界。
- 參數(shù)彈出方式侨嘀。函數(shù)調(diào)用結(jié)束后需要將壓入棧中的參數(shù)全部彈出,以使得棧在函數(shù)調(diào)用前后保持一致捂襟。這個彈出的工作可以由調(diào)用方來完成咬腕,也可以由被調(diào)用方來完成。
- 函數(shù)名修飾方式葬荷。函數(shù)名在編譯時會被修改涨共,調(diào)用慣例可以決定如何修改函數(shù)名。
函數(shù)調(diào)用慣例在函數(shù)聲明和函數(shù)定義時都可以指定宠漩,語法格式為:
返回值類型 調(diào)用慣例 函數(shù)名(函數(shù)參數(shù))
在函數(shù)聲明處是為調(diào)用方指定調(diào)用慣例举反,而在函數(shù)定義處是為被調(diào)用方(也就是函數(shù)本身)指定調(diào)用慣例。
__cdecl是C語言默認(rèn)的調(diào)用慣例扒吁,在平時編程中火鼻,我們其實(shí)很少去指定調(diào)用慣例,這個時候就使用默認(rèn)的 __cdecl。
注意:__cdecl 并不是標(biāo)準(zhǔn)關(guān)鍵字魁索,上面的寫法在 VC/VS 下有效融撞,但是在 GCC 下,要使用 attribute((cdecl))粗蔚。
除了 cdecl尝偎,還有其他調(diào)用慣例,請看下表:
calling convention
所有的文件都引用了crt0.c 所以實(shí)現(xiàn)在這個文件
windows 下mainCRTStartup調(diào)用堆棧
這不是實(shí)際的call stack鹏控,這是被整理過的call stack冬念,里面只包含我們要關(guān)心的一些關(guān)鍵點(diǎn)
1 分配內(nèi)存
2 io 初始化,比如printf cout
3 4 5 6都是字符串相關(guān)的一些初始化
7 c相關(guān)初始化
1 2可以參考c++內(nèi)存管理
c++內(nèi)存管理可以參考這牧挣,這里不做重復(fù)的描述,同樣此課程的ppt依然會放到最后作為參考
第一次分配內(nèi)存130h 的實(shí)際來源 32*8*(256是實(shí)際需要的內(nèi)存sizeof(ioinfo))+4*9(debug信息以及cookie信息) = 124h ,16進(jìn)制對齊就是130h 這里對應(yīng)進(jìn)入main函數(shù)前的第二步操作ioinit()
之后首先會分配一系列內(nèi)存醒陆,對應(yīng)這里對應(yīng)進(jìn)入main函數(shù)前的第三四五六七步操作
0x390178 + 8*128 = 0x390578
除0號鏈表外瀑构,其他鏈表都指向自己為空鏈表
此時的切片,0號鏈表有空閑區(qū)間
另外這里黃色區(qū)域?yàn)閏ookie刨摩,這里記錄了上區(qū)塊大小和本區(qū)塊大小寺晌,用來定位上下區(qū)塊確切的地址,長度以單元記澡刹,每個單元8字節(jié)
這里可以根據(jù)sbh分配內(nèi)存的原理與實(shí)際中內(nèi)存地址的數(shù)據(jù)對應(yīng)呻征,可以驗(yàn)證
程序一進(jìn)來會開長度為64的數(shù)組,每個節(jié)點(diǎn)malloc_crt(32*sizeof(inifo))
因此程序最多可以有2048個file handle(廣義)
少畫一格罢浇,四個字節(jié)陆赋,用來做16倍數(shù)對齊
所有c/c++第一次內(nèi)存分配大小都是256,用來處理io嚷闭,分配一個ioinfo結(jié)構(gòu)體的大小