C++編譯鏈接原理

從底層剖析程序從編譯到運行的整個過程

三個階段

    • 一、編譯階段
    • 二、鏈接階段
    • 三、運行階段

為了方便解釋,給出兩端示例代碼,下面圍繞代碼進行實驗:

//sum.cpp
int gdata = 10;
int sum(int a,int b)
{return a+b;
}
//main.cpp
extern int gdata;
int sum(int ,int);static int stat;int data = 20;int main()
{int a = gdata;int b = data;int ret = sum(a,b);return 0;
}

前兩個階段:
在這里插入圖片描述

一、編譯階段

在這里插入圖片描述
三件重要的事情:
編譯階段只關注自己模塊內的事情
編譯階段不分配虛擬空間地址,無法運行
目標文件由各個段組成

編譯階段的產物是可重定位的二進制目標文件,由各個段組成
在這里插入圖片描述
一、符號表(.symtab段)
查看符號表命令:objdump -t main.o
在這里插入圖片描述
1.符號表中存儲程序產生的符號,如
靜態全局變量stat的符號為_ZL4stat ,定義在.bss區域
全局變量data的符號為data,定義在.data區域
主函數main()的符號為main,定義在.text區域
外部變量gdata的符號為gdata,定義為UND,表示符號的引用,不知道在哪里定義
外部函數sum(int,int)的符號為_Z3sumii,定義為UND,表示符號的引用,不知道在哪里定義

2.符號表中可以看到變量的鏈接屬性
l:表示lcoal,符號只能在當前文件可見,內部鏈接屬性
g:表示global,符號可以在所有文件可見,外部鏈接屬性

所以鏈接的時候鏈接器只能看見gloal的符號 看不到lcoal的符號
這就解釋了靜態全局變量/函數 和普通全局變量/函數同名的問題
在多個文件中可以定義名字相同的靜態全局變量/函數,因為local屬性鏈接器不可見,但若多個文件中普通的全局變量/函數重名,因為具有global屬性,鏈接的時候符號解析就會沖突

3.編譯過程中變量不分配虛擬空間地址
我們查看以下.text段,注意需要帶有-g輸出調試信息
g++ -c main.cpp -g
objdump -S main.o
在這里插入圖片描述觀察,編譯階段產生了二進制機器碼,但是不分配虛擬空間地址,所以地址先用0替代,即編譯階段指令沒法用,需要等鏈接階段分配虛擬地址補上地址才有用,這就是目標文件無法運行的原因之一
4.查看目標文件的各個段
命令:readelf -S main.o
在這里插入圖片描述

二、鏈接階段

在這里插入圖片描述

鏈接所有的編譯完成的目標文件(.o)和靜態庫文件(.a)
鏈接步驟:
步驟一:
將所有的目標文件的各個段進行合并
main.o的.text段和sum.o的.text段合并
main.o的.data段和sum.o的.data段合并
main.o的.bss和sum.o的.bss段合并
合并后進行符號解析
如鏈接階段符號為UND(符號引用)的,都需要找到該符號定義的地方,如果沒有找到=符號未定義,找到多個定義=符號重定義
UND 找到定義解析成具體 .text .data ..

步驟二:
符號的重定位(重定向)
符號解析之后,給所有的符號分配虛擬地址空間,成為了可執行文件

驗證
使用鏈接器自己鏈接::ld -e main sum.o main.o
查看符號表:objdump -t a.out
在這里插入圖片描述
可以看到所有符號均有定義的段,無UND符號引用的情況
所有符號均分配了地址(看第一列)

再看看代碼段.text
在這里插入圖片描述
之前機器碼缺少地址的,現在也都補充上了,所以變成了可以運行的二進制機器碼(指令)

補充1:
看一下可執行文件的文件頭信息
在這里插入圖片描述

.text段的信息
在這里插入圖片描述
可以發現,可執行文件頭記錄了程序入口指令地址,所以CPU知道從哪個指令開始執行(這里是main函數作為入口)

補充2:
可執行文件所有的段都和二進制目標文件相同,多了一個programa headers段,用來告訴操作系統,運行這個程序的時候,把哪些內容加載進內存(數據段 指令段),注意:不是所有的段都需要加載進內存的
查看programa headers段:readelf -l a.out
在這里插入圖片描述

三、運行階段

在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/43187.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/43187.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/43187.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Stream流的簡單用法

filter //stream流中的filter //filter 方法用于通過設置的條件過濾出元素。以下代碼片段使用 filter 方法過濾掉空字符串&#xff1a; List<String> filter Arrays.asList("mz", "", "mz55", "m", "MZ"); Stream&l…

初始redis:在Ubuntu上安裝redis

1.先切換到root用戶 使用su命令切換到root 2.使用apt命令來搜索redis相關的軟件包 命令&#xff1a;apt search redis 3.下載redis 命令&#xff1a; apt install redis 在Ubuntu 20.04中 &#xff0c;下載的redis版本是redis5 4.查看redis狀態 命令&#xff1a; netst…

Python自動化測試系列[v1.0.0][高效自動化設計]

Python多線程應用于自動化測試 將多線程在測試巧妙地應用&#xff0c;確實會帶來很多好處&#xff0c;并且這是充分利用機器資源執行高效率測試很好的方式 # -*- coding: utf-8 -*- import threading from time import ctime import time from selenium import webdriverdef …

LLM 入門與實踐(四) Yi 部署與分析

本文截取自20萬字的《PyTorch實用教程》&#xff08;第二版&#xff09;&#xff0c;敬請關注&#xff1a;《Pytorch實用教程》&#xff08;第二版&#xff09;無論是零基礎入門&#xff0c;還是CV、NLP、LLM項目應用&#xff0c;或是進階工程化部署落地&#xff0c;在這里都有…

python對象

類 我們目前所學習的對象都是Python內置的對象但是內置對象并不能滿足所有的需求&#xff0c;所以我們在開發中經常需要自定義一些對象類&#xff0c;簡單理解它就相當于一個圖紙。在程序中我們需要根據類來創建對象類就是對象的圖紙&#xff01;我們也稱對象是類的實例&#…

JAVA--IO流

一、IO流什么&#xff1f; I/O是Input/output的縮寫&#xff0c;用于處理設備之間的數據傳輸。如讀/寫文件、網絡通訊。 java程序中&#xff0c;對于數據的輸入、輸出是以流&#xff08;Stream)的方式進行。 Java.io包下提供了各種流類和接口&#xff0c;用以獲取不同種類的數…

web自動化(六)unittest 測試報告跳過用例

三種類型測試報告&#xff1a;unittest.TextTestRunner、BeautifulReport、HTMLTestRunner Python3.0 無法直接安裝 HTMLTestRunner 安裝 XTestRunner pip install XTestRunner安裝 BeautifulReport pip install BeautifulReportimport unittestclass TestSkipCase(unittest…

ELfK logstash filter模塊常用的插件 和ELFK部署

ELK之filter模塊常用插件 logstash filter模塊常用的插件&#xff1a; filter&#xff1a;表示數據處理層&#xff0c;包括對數據進行格式化處理、數據類型轉換、數據過濾等&#xff0c;支持正則表達式 grok 對若干個大文本字段進行再分割成一些小字段 (?<字段名…

【算法篇】KMP算法,一種高效的字符串匹配算法

我們今天了解一個字符串匹配算法-KMP算法&#xff0c;內容難度相對來說較高&#xff0c;建議先收藏再細品&#xff01;&#xff01;&#xff01; KMP算法的基本概念 KMP算法是一種高效的字符串匹配算法&#xff0c;由D.E.Knuth&#xff0c;J.H.Morris和V.R.Pratt提出的&#…

LLMs之gptpdf:gptpdf的簡介、安裝和使用方法、案例應用之詳細攻略

LLMs之gptpdf&#xff1a;gptpdf的簡介、安裝和使用方法、案例應用之詳細攻略 目錄 gptpdf的簡介 1、處理流程 第一步&#xff0c;使用 PyMuPDF 庫&#xff0c;對 PDF 進行解析出所有非文本區域&#xff0c;并做好標記&#xff0c;比如: 第二步&#xff0c;使用視覺大模型&…

離婚后,孩子就讀私立高中的高昂學費誰承擔?

江蘇省南京市六合區人民法院審結一起撫養費糾紛案件&#xff0c;認定夫妻雙方在決定孩子教育事務上均存在責任&#xff0c;為保障臨近高考的未成年子女的切身利益&#xff0c;認定由夫妻雙方按比例承擔教育費。   2015年6月&#xff0c;李某與王某離婚&#xff0c;雙方之子小…

PCL 有序點云的法線估計(使用積分圖進行法線估計)

使用積分圖進行法線估計 一、概述1.1 概念1.2 有序點云與無序點云1.2.1 有序點云1.2.2 無序點云1.3 代碼講解二、代碼實現三、結果示例一、概述 1.1 概念 使用積分圖進行法線估計:計算一個有序點云的法線,注意該方法只適用于有序點云。 1.2 有序點云與無序點云 有序點云與無…

MySQL安裝時initializing database失敗

問題頁面&#xff1a; 解決方法&#xff1a; 1.勾選紅框中的選項&#xff1a; 2.將下圖紅框中全部改為英文&#xff1a; 然后一路next就可以了。

cs231n作業1——KNN

參考文章&#xff1a;assignment1——KNN KNN 測試時分別計算測試樣本和訓練集中的每個樣本的距離&#xff0c;然后選取距離最近的k個樣本的標簽信息來進行分類。 方法1&#xff1a;Two Loops for i in range(num_test):for j in range(num_train):dist X[i, :] - self.X…

vue3使用方式匯總

1、引入iconfont阿里圖庫圖標&#xff1a; 1.1 進入阿里圖標網站&#xff1a; iconfont阿里&#xff1a;https://www.iconfont.cn/ 1.2 添加圖標&#xff1a; 1.3 下載代碼&#xff1a; 1.4 在vue3中配置代碼&#xff1a; 將其代碼復制到src/assets/fonts/目錄下&#xff1…

Mysql之Using index for skip scan

一、Using index for skip scan 在 MySQL 中&#xff0c;EXPLAIN 語句用于顯示查詢執行計劃&#xff0c;幫助我們理解查詢是如何被執行的&#xff0c;以及如何優化查詢。其中&#xff0c;Extra 列提供了關于查詢執行的一些額外信息。當 Extra 列顯示 Using index for skip sca…

CF F. Alex‘s whims

原題鏈接&#xff1a;Problem - 1899F - Codeforces 題目大意&#xff1a;要求構建出一顆樹&#xff0c;多次詢問樹的葉節點之間的距離有沒有達到要求的距離&#xff0c;如果有直接輸出-1 -1 -1&#xff0c;如果沒有可以斷開一條邊和連上一條邊&#xff0c;輸出x y z&#xff…

mp4視頻太大怎么壓縮不影響畫質,mp4文件太大怎么變小且清晰度高

在數字化時代&#xff0c;我們常常面臨視頻文件過大的問題。尤其是mp4格式的視頻&#xff0c;文件大小往往令人望而卻步。那么&#xff0c;如何在不影響畫質的前提下&#xff0c;有效地壓縮mp4視頻呢&#xff1f;本文將為您揭秘幾種簡單實用的壓縮技巧。 在分享和存儲視頻時&am…

Open3D 計算點云的歐式距離

目錄 一、概述 1.1歐式距離定義 1.2作用和用途 二、代碼實現 2.1關鍵函數 2.2完整代碼 三、實現效果 3.1原始點云 3.2處理后點云 一、概述 在Open3D中&#xff0c;compute_point_cloud_distance函數用于計算兩個點云之間的距離。具體來說&#xff0c;它計算的是源點云…

【計算機網絡仿真】b站湖科大教書匠思科Packet Tracer——實驗16 路由信息協議RIP

一、實驗目的 1.驗證RIP協議的作用&#xff1b; 二、實驗要求 1.使用Cisco Packet Tracer仿真平臺&#xff1b; 2.觀看B站湖科大教書匠仿真實驗視頻&#xff0c;完成對應實驗。 三、實驗內容 1.構建網絡拓撲&#xff1b; 2.驗證RIP協議。 四、實驗步驟 1.構建網絡拓撲 …