《基礎知識 編譯與底層》

2021-09-25 11:18:11 字數 3057 閱讀 1705

對於c++原始檔,從文字到可執行檔案一般需要四個過程

1、預處理階段:對源**檔案中檔案包含關係(標頭檔案)、預編譯語句(巨集定義)進行分析和替換,生成預編譯檔案。

2、編譯階段:將經過預處理後的預編譯檔案轉換成特定彙編**,生成彙編檔案

3、彙編階段:將編譯階段生成的彙編檔案轉化成機器碼,生成可重定位目標檔案

【c++標頭檔案的包含順序研究】、【區別】

《c++程式設計思想》p432提到:標頭檔案被包含的順序是從「最特殊到最一般」。這就是,在本地目錄的任何標頭檔案首先被包含。然後是我們自己的所有「工具」標頭檔案,隨後是第三方庫標頭檔案,接著是標準c++庫標頭檔案和c庫標頭檔案。

【優點】:《c++程式設計思想》則很容易讓你清楚知道你所定義的介面是否和系統庫及第三方庫發生衝突。

《google c++ 程式設計風格指南》遵循的順序「從一般到特殊」的原則:c標準庫、c++標準庫、其它庫的標頭檔案、你自己工程的標頭檔案  中漏了最前面的一項:作業系統級別的標頭檔案,比如上面的例子sys/types.h估計不能歸入c標準庫,而是linux作業系統提供的sdk吧。因此我覺得更準確的說法應該是:os sdk .h , c標準庫、c++標準庫、其它庫的標頭檔案、你自己工程的標頭檔案。

【優點】:能大量減少隱藏的標頭檔案依賴。

加雙引號表示,應用程式先在當前的資料夾裡面尋找該標頭檔案,若沒有找到,再到系統資料夾裡去找。一般加雙引號多為自己編寫的標頭檔案。

加尖括號則表示,應用程式直接到系統資料夾去找該檔案。這類多為系統標頭檔案。

【原理】:malloc函式用於動態分配記憶體。

為了減少記憶體碎片和系統呼叫的開銷,malloc其採用記憶體池的方式,先申請大塊記憶體作為堆區,然後將堆區分為多個記憶體塊,以塊作為記憶體管理的基本單位。當使用者申請記憶體時,直接從堆區分配一塊合適的空閒塊。malloc採用隱式鍊錶結構將堆區分成連續的、大小不一的塊,包含已分配塊和未分配塊;同時malloc採用顯示鍊錶結構來管理所有的空閒塊,即使用乙個雙向鍊錶將空閒塊連線起來,每乙個空閒塊記錄了乙個連續的、未分配的位址。

當進行記憶體分配時,malloc會通過隱式鍊錶遍歷所有的空閒塊,選擇滿足要求的塊進行分配;當進行記憶體合併時,malloc採用邊界標記法,根據每個塊的前後塊是否已經分配來決定是否進行塊合併。

【申請記憶體】:malloc在申請記憶體時,一般會通過brk或者mmap系統呼叫進行申請。

【brk】:其中當申請記憶體小於128k時,會使用系統函式brk在堆區中分配;

【mmap】:而當申請記憶體大於128k時,會使用系統函式mmap在對映區分配。

在c++中,虛擬記憶體分為**段、資料段、bss段、堆區、檔案對映區以及棧區六部分。(??四區還是六區)

【**段】:包括唯讀儲存區和文字區,其中唯讀儲存區儲存字串常量,文字區儲存程式的機器**。

【資料段】:儲存程式中已初始化的全域性變數和靜態變數

【bss段】:儲存未初始化的全域性變數和靜態變數(區域性+全域性),以及所有被初始化為0的全域性變數和靜態變數。

【堆區】:呼叫new/malloc函式時在堆區動態分配記憶體,同時需要呼叫delete/free來手動釋放申請的記憶體。

【記憶體分配】:在當前的windows 32 位作業系統中預設核心空間和使用者空間的比例是1:1(2gb 的核心空間,2gb 的使用者空間),而在32 位linux系統中預設的比例是1:3(1gb 的核心空間,3gb 的使用者空間)。

【記憶體分配方式】:靜態儲存區 棧 堆 的記憶體分配

1,從靜態儲存區域分配記憶體。程式編譯的時候記憶體已經分配好了,並且在程式的整個執行期間都存在,例如全域性變數。

2,在棧上建立。在執行函式時,函式內區域性變數的儲存單元可以在棧上建立,函式結束時這些儲存單元自動被釋放。

處理器的指定集中有關於棧記憶體的分配運算,因此效率比較高,但是分配的記憶體容量有限。

3,在堆上分配記憶體,亦稱動態記憶體分配,程式在執行的時候用malloc函式或new運算子申請任意大小的記憶體,程式設計師

要用free函式或delete運算子釋放記憶體。動態記憶體使用非常靈活,但問題也很多。

記憶體洩漏(memory leak)是指由於疏忽或錯誤造成了程式未能釋放掉不再使用的記憶體的情況。記憶體洩漏並非指內存在物理上的消失,而是應用程式分配某段記憶體後,由於設計錯誤,失去了對該段記憶體的控制,因而造成了記憶體的浪費。

(簡單地說就是申請了一塊記憶體空間,使用完畢後沒有釋放掉。由程式申請的一塊記憶體,且沒有任何乙個指標指向它,那麼這塊記憶體就洩露了。)

【如何檢測記憶體洩露】

【如何避免】

智慧型指標。因為智慧型指標可以自動刪除分配的記憶體。智慧型指標和普通指標類似,只是不需要手動釋放指標,而是通過智慧型指標自己管理記憶體的釋放。

【如何處理】

1)從程式內部重新編譯。養成良好的編碼習慣,盡量在涉及記憶體的程式段,檢測出記憶體洩露。

2)結束程式,記憶體自然就會被作業系統**。

3)重新啟動電腦後,立刻恢復。

1、new分配記憶體按照資料型別進行分配,malloc分配記憶體按照指定的大小分配;

2、new返回的是指定物件的指標,而malloc返回的是void*,因此malloc的返回值一般都需要進行型別轉化。

3、new不僅分配一段記憶體,而且會呼叫建構函式,malloc不會。

4、new分配的記憶體要用delete銷毀,malloc要用free來銷毀;delete銷毀的時候會呼叫物件的析構函式,而free則不會。

5、new是乙個操作符可以過載,malloc是乙個庫函式。

6、malloc分配的記憶體不夠的時候,可以用realloc擴容。擴容的原理?new沒用這樣操作。

7、new如果分配失敗了會丟擲bad_malloc的異常,而malloc失敗了會返回null。

8、申請陣列時: new一次分配所有記憶體,多次呼叫建構函式,搭配使用delete,delete多次呼叫析構函式,銷毀陣列中的每個物件。而malloc則只能sizeof(int) * n。

編譯基礎知識

cpp生成可執行程式 g test.cpp o test 靜態庫gcc c cjson.c ar rcs libcjson.a cjson.o 動態庫gcc c o cjson.o fpic cjson.c gcc shared o libcjson.so cjson.o 或直接連寫 gcc sha...

反編譯基礎知識

嚴正宣告 本文相關反編譯技術僅限於技術研究使用,不能用於非法目的,否則後果自負.apktool 逆向apk檔案的工具 官方 apktool主要用於逆向apk檔案,可以將資源解碼,並在修改之後可以重新構建它們.它還可以用來重新構建apk.1.1 功能 將資源解碼成近乎原始的形式 包括resources...

底層硬體相關的基礎知識

按照硬碟材質分為兩大類hdd hard disk driver 傳統硬碟,即機械硬碟 ssd solid state disk 固態硬碟 按照介面型別區分有ata和scsi是兩大介面型別,這裡所謂的硬碟介面,就是硬碟與主機板之間的連線方式。雖然sata和sas是兩種不同分支的進化型,但是,sas卻可...