GCC編譯/連接/優化等選項

1. GCC編譯/連接/優化等選項

  • 1. GCC編譯/連接/優化等選項
    • 1.1. 簡介
    • 1.2. 常用選項
      • 1.2.1. -c -E -S -o
      • 1.2.2. -L<path> -l<library>
      • 1.2.3. -D<macro>
      • 1.2.4. -I<path>
    • 1.3. 代碼生成和優化
      • 1.3.1. -std=<standard>
      • 1.3.2. -shared
      • 1.3.3. -fPIC
      • 1.3.4. -static
      • 1.3.5. -O0 -O1 -O2 -O3 -Os
      • 1.3.6. -ffunction-sections-fdata-sections
    • 1.4. 調試與警告選項
      • 1.4.1. -g -ggdb
      • 1.4.2. -Wall -Werror -Wextra
      • 1.4.3. -Wno-pointer-sign
      • 1.4.4. -fno-strict-aliasing -fstrict-aliasing
    • 1.5. 安全與連接選項
      • 1.5.1. -z noexecstack -z relro -z now
      • 1.5.2. -Wl,option
      • 1.5.3. -Wl,--strip-all,--gc-sections,--as-needed
      • 1.5.4. -Wl,--verbose,-soname,<name>
      • 1.5.5. -Wl,-T,<script>,-Ttext,<address>,-Tdata,<address>
    • 1.6. 高級選項
      • 1.6.1. -pedantic
      • 1.6.2. -fsanitize=<type>
      • 1.6.3. -rpath <path>

1.1. 簡介

GCC 編譯流程分為四個階段:預處理、編譯、匯編、鏈接,這里講解gcc用到的一些參數

  • GCC 原生選項:直接由 GCC 處理,如:

    • -o(輸出文件名)
    • -lm(鏈接數學庫 libm)
    • -Wall(啟用警告)
    • -O2(優化級別)
  • 鏈接器專屬選項:需通過 -Wl, 傳遞給鏈接器(如 ld),如:

    • –gc-sections(移除未使用的節)
    • -soname(設置共享庫運行時名稱)
    • -T(使用自定義鏈接腳本)

1.2. 常用選項

1.2.1. -c -E -S -o

-E 僅進行預處理,輸出預處理后的代碼。
gcc -E source.c -o source.i

-c 只進行編譯,不進行鏈接,生成目標文件(.o)
gcc -c source.c # 生成 source.o

-S 生成匯編代碼(.s)。
gcc -S source.c # 生成 source.s

-o 指定輸出文件的名稱
gcc source.c -o program

1.2.2. -L<path> -l<library>

-l 鏈接指定的庫(如-lm鏈接數學庫)。
-L 指定庫文件的搜索路徑。
gcc source.c -L/path/to/lib -lmylib

1.2.3. -D<macro>

定義宏(等價于在代碼中使用#define)。

1.2.4. -I<path>

指定頭文件的搜索路徑。

1.3. 代碼生成和優化

1.3.1. -std=<standard>

指定 C/C++ 標準(如-std=c99、-std=c++17)。

1.3.2. -shared

生成共享庫(.so)

1.3.3. -fPIC

生成位置無關代碼(用于共享庫)。

1.3.4. -static

靜態鏈接所有庫(生成獨立可執行文件)。
gcc -static source.c

1.3.5. -O0 -O1 -O2 -O3 -Os

選項優化目標編譯時間代碼體積運行性能典型場景
-O0無優化(調試)最快最大最慢開發調試
-O1平衡性能與時間較快較小一般日常開發的 release 版本
-O2優化性能較長中等生產環境默認
-O3最高性能最長最大最快高性能計算
-Os最小代碼體積較長最小接近- O2 嵌入式系統、固件

1.3.6. -ffunction-sections-fdata-sections

-ffunction-sections:將每個函數放在獨立的 ELF 節(section)中。
-fdata-sections:將每個全局變量放在獨立的節中。
目的:配合鏈接器選項 -Wl,--gc-sections(垃圾回收),在最終二進制文件中移除未使用的函數和變量,減小文件體積。

1.4. 調試與警告選項

1.4.1. -g -ggdb

-g 生成調試信息,用于 GDB 調試。
-ggdb 生成更詳細的 GDB 調試信息。

一般配合 -O0 使用, 優化選項(如 -O2)可能會改變代碼結構,導致調試信息與實際執行不匹配。

選項調試信息格式適用調試器文件大小調試體驗
-g標準 DWARF通用較小基本調試
-ggdbGDB 擴展GDB 專用較大高級調試

1.4.2. -Wall -Werror -Wextra

-Wall 啟用常見的編譯警告(如未使用的變量、隱式轉換等)。
-Werror 將所有警告視為錯誤,強制修復警告。
-Wextra 啟用額外的警告(如未初始化的變量、冗余代碼等)。一般用的比較少

1.4.3. -Wno-pointer-sign

-Wno-pointer-sign 是 GCC 編譯器的一個警告選項,用于禁用關于指針符號不匹配的警告
禁用警告:通過 -Wno-pointer-sign 可以關閉這類警告,避免編譯時產生干擾信息。
相反選項:對應的啟用警告選項是 -Wpointer-sign,但通常通過 -Wall 或 -Wextra 自動啟用。

1.4.4. -fno-strict-aliasing -fstrict-aliasing

-fstrict-aliasing(默認啟用):嚴格遵循別名規則,進行激進優化。
-fno-strict-aliasing:禁用規則,允許不同類型指針別名,可能導致顯著的性能損失。

  • 禁用 GCC 的嚴格別名規則優化,允許不同類型指針指向同一塊內存。
  • 禁用優化會降低性能,建議優先修改代碼以符合嚴格別名規則(如使用 union)。
  • 適用于遺留代碼或依賴類型雙關(type punning)的場景(如底層硬件訪問)。
int a = 1;
float* f = (float*)&a;  // 違反規則
*f = 3.14f;
printf("%d\n", a);  // 可能輸出 1(而非預期的修改后的值)

解決方案:

  • 使用 union 實現類型雙關,確保類型兼容。
  • 使用字符指針轉換
  • 使用 memcpy

1.5. 安全與連接選項

1.5.1. -z noexecstack -z relro -z now

  • -z noexecstack
    • 現代操作系統(如 Linux)支持內存區域的 NX 位(No-eXecute),通過該選項將棧標記為不可執行。
    • 若攻擊者嘗試在棧上執行惡意代碼,會觸發內存訪問異常。
    • 某些動態鏈接庫(如使用 setjmp/longjmp 的庫)可能需要可執行棧,此時需謹慎使用。
    • 現代 Linux 發行版默認啟用 NX 保護,但通過 -z execstack 可禁用(不推薦)。
  • -z relro (Relocation Read-Only)
    • 功能:啟用只讀重定位(Relocation Read-Only)。
    • 防御機制:將全局偏移表(GOT,Global Offset Table)和動態符號表標記為只讀,防止攻擊者修改這些表中的函數地址。
  • -z now
    • 功能:強制鏈接器立即綁定所有符號(而非延遲綁定)。
    • 防御機制:減少動態加載時的符號表修改機會,增強 RELRO 的安全性。

1.5.2. -Wl,option

-Wl,option 是 GCC 編譯器用于將參數傳遞給鏈接器(如 ld)的語法。通過 , 分隔多個選項,例如 -Wl,–gc-sections,-Map=output.map

gcc source.c -Wl,-o,program.out       # -o 選項,指定輸出文件名,等價于 gcc source.c -o program.out
gcc source.c -Wl,-e,my_entry_point    # -e 選項,指定入口點,代替 main 函數,等價于 gcc source.c -emy_entry_point
gcc source.c -Wl,-L,/path/to/lib      # -L 選項,指定庫搜索路徑,等價與 gcc source.c -L/path/to/lib
gcc source.c -Wl,-l,m                 # -l 選項,等價與 gcc source.c -lm,建議直接使用 -lm,語法更簡潔。
  • 選項類別 必須使用 -Wl, 的典型選項
    • 代碼優化 --gc-sections, --as-needed
    • 內存布局 -T, -Ttext, -Tdata
    • 共享庫 -soname, --version-script
    • 安全增強 -z noexecstack, -z relro, -z now
    • 調試 --verbose, --cref

1.5.3. -Wl,--strip-all,--gc-sections,--as-needed

gcc source.c -Wl,--strip-all,--gc-sections,--as-needed
gcc source.c -Wl,--wrap,malloc  # 使用 __wrap_malloc 替代 malloc
  • --gc-sections 移除未使用的代碼和數據段(需配合 -ffunction-sections 和 -fdata-sections)。
    • 用于移除可執行文件中未使用的代碼和數據段(sections),從而減小二進制文件體積。
    • 若某個節被標記為 USED(如通過 attribute((used))),則不會被回收。
    • 啟用 GC 會增加鏈接時間(需分析所有符號),但通常對運行時性能無影響。
    • 若二進制體積不是關鍵因素,可關閉此選項以加快編譯。
    • -O2 會自動啟用一些內聯優化,但無法替代 --gc-sections 的全局代碼刪除能力。
    • 驗證:使用 size 命令對比文件大小
  • --strip-all 或 --strip-debug 移除符號表和調試信息。
  • --as-needed 僅鏈接真正使用的共享庫(減少依賴)。
  • --wrap <symbol> 允許替換標準庫函數(用于測試或鉤子)。

1.5.4. -Wl,--verbose,-soname,<name>

gcc source.c -Wl,--verbose,-soname,libmylib.so.1

--verbose 輸出鏈接過程的詳細信息。
-soname <name> 設置共享庫的運行時名稱(用于版本控制)。

1.5.5. -Wl,-T,<script>,-Ttext,<address>,-Tdata,<address>

gcc source.c -Wl,-T,memory_layout.ld
gcc source.c -Wl,-Ttext,0x10000
gcc source.c -Wl,-Tdata,0x20000

-T <script> 使用自定義鏈接腳本(用于嵌入式系統或特殊內存布局)。
-Ttext <address> 指定代碼段(.text)的加載地址。
-Tdata <address> 指定數據段(.data)的加載地址。

1.6. 高級選項

1.6.1. -pedantic

嚴格遵循語言標準,拒絕非標準特性。

1.6.2. -fsanitize=<type>

啟用運行時檢查(如內存泄漏、未定義行為)。

1.6.3. -rpath <path>

設置運行時庫搜索路徑(替代 LD_LIBRARY_PATH)。

gcc source.c -Wl,-rpath,/path/to/lib

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

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

相關文章

FFmpeg 壓縮視頻文件

文章目錄 FFmpeg 壓縮視頻文件基本壓縮命令&#xff08;保持 MP4 格式&#xff09;轉換為其他格式示例&#xff1a;關鍵參數說明&#xff1a;額外優化選項&#xff1a; 在FFmpeg中使用多線程加速1. 幀級多線程 (frame-level multithreading)2. 切片級多線程 (slice-level multi…

Ubuntu 系統通過防火墻管控 Docker 容器

Ubuntu 系統通過防火墻管控 Docker 容器指南 一、基礎防火墻配置 # 啟用防火墻 sudo ufw enable# 允許 SSH 連接&#xff08;防止配置過程中斷聯&#xff09; sudo ufw allow 22/tcp二、Docker 配置調整 # 編輯 Docker 配置文件 sudo vim /etc/docker/daemon.json配置文件內…

虛擬機新增硬盤,與數據掛載

我有個虛擬機&#xff0c;當時選擇了獨立文件&#xff0c;現在遇到個問題&#xff0c;硬盤不夠了&#xff0c;索性加了一個新硬盤&#xff0c;現在想把數據庫的數據映射到這個新的硬盤處理。 羅列硬盤 lsblk我得是sdb是新硬盤 2. 分區 sudo fdisk /dev/sdb交互操作&#xff…

go語言學習 第10章:面向對象編程

第10章&#xff1a;面向對象編程 面向對象編程&#xff08;OOP&#xff09;是一種編程范式&#xff0c;它使用“對象”來表示數據和方法&#xff0c;并通過類來定義對象的結構和行為。Go語言雖然不是傳統的面向對象語言&#xff0c;但它通過結構體&#xff08;struct&#xff…

android計算器代碼

本次作業要求實現一個計算器應用的基礎框架。以下是布局文件的核心代碼&#xff1a; <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent"android:layout_height"match_parent"andr…

Go 語言接口詳解

Go 語言接口詳解 核心概念 接口定義 在 Go 語言中&#xff0c;接口是一種抽象類型&#xff0c;它定義了一組方法的集合&#xff1a; // 定義接口 type Shape interface {Area() float64Perimeter() float64 } 接口實現 Go 接口的實現是隱式的&#xff1a; // 矩形結構體…

我們來學mysql -- 8.4版本記錄慢查詢

記錄慢查詢 開啟慢查詢的配置查看慢查詢狀態動態開啟慢查詢日志永久開啟配置log_throttle_queries_not_using_indexes 記錄慢查詢對性能的影響實際案例說明第一條記錄第二條記錄第三條記錄第四條記錄 開啟慢查詢的配置 查看慢查詢狀態 - 執行 show variables like slow_quer…

2025 年中國大學生程序設計競賽全國邀請賽(鄭州)暨第七屆CCPC河南省大學生程序設計競賽(補題)

文章目錄 前言F、幻形之路G、直徑與最大獨立集H&#xff0c;樹論函數M&#xff0c; 川陀航空學院總結 前言 本次比賽&#xff0c;只能說太多沒接觸的知識了&#xff0c;還有太容易被題面嚇住。 F、幻形之路 題目鏈接&#xff1a;幻形之路 解題思路&#xff1a; 對于這一題只…

如何使用k8s安裝redis呢

在Kubernetes (k8s) 上安裝Redis 在Kubernetes上安裝Redis有幾種方法&#xff0c;下面我將介紹兩種常見的方式&#xff1a;使用StatefulSet直接部署和使用Helm chart部署。 一、安裝redis 1.1 拉去ARM鏡像&#xff08;7.4.2&#xff09; docker pull registry.cn-hangzhou.ali…

SpringBoot的5種日志輸出規范策略

在企業級應用開發中&#xff0c;合理規范的日志記錄是系統穩定運行、問題排查和性能優化的關鍵保障。 SpringBoot作為流行的Java開發框架&#xff0c;提供了強大而靈活的日志支持&#xff0c;但如何建立統一、高效的日志輸出規范卻是許多團隊面臨的挑戰。 本文將介紹SpringBo…

Python Cookbook-7.11 在 PostgreSQL 中儲存 BLOB

任務 需要將 BLOB 存入一個 PostgreSQL 數據庫。 解決方案 PostgreSQL7.2 以及更新的版本支持大對象,而psycopg 模塊提供了二進制轉義函數: import psycopg,cPickle #連接到數據庫,用你的本機來測試數據庫,并獲得游標 connection = psycopg.connect("dbname = test…

Android端口轉發

如上圖所示&#xff0c;有一個Android設備&#xff0c;Android設備里面有主板&#xff0c;主板上有網絡接口和Wi-Fi&#xff0c;網絡接口通過網線連接了一個網絡攝像頭&#xff0c;這就跟電腦一樣&#xff0c;電腦即可以通過網線接入一個網絡&#xff0c;也可以同時用Wi-Fi接入…

Unity基礎-協程

Unity基礎-協程 四、協程 概述 協程&#xff08;Coroutine&#xff09;&#xff0c;本質上并不是多線程&#xff0c;而是在當前線程中將代碼分時執行&#xff0c;不卡主線程。可以理解為&#xff0c;協程會把可能使主線程卡頓的程序分時分布進行。 協程通常用來&#xff1a;…

UniApp組件封裝,2025年最新HarmonyOS鴻蒙模塊化開發項目式教程

一、環境配置與前置條件 ?開發工具要求? HBuilderX 4.64&#xff08;鴻蒙插件已預裝&#xff09;DevEco Studio 5.0.3.400&#xff08;真機調試必備&#xff09;鴻蒙離線SDK&#xff08;通過HBuilderX導入&#xff0c;每個項目獨立配置&#xff09; ?項目初始化 # 創建Vu…

C++ 精簡知識點

目錄 一、核心語法 1.指針VS引用 2. 類與對象&#xff08;必寫代碼&#xff09; 3. 繼承與多態&#xff08;必寫代碼&#xff09; 4. 模板&#xff08;必寫代碼&#xff09; 5.智能指針 6. 異常處理&#xff08;必寫結構&#xff09; 二、簡答題速記 三、考試應急策略 一…

7.Vue的compute計算屬性

3.8. 【computed】 作用&#xff1a;根據已有數據計算出新數據&#xff08;和Vue2中的computed作用一致&#xff09;。 <template><div class"person">姓&#xff1a;<input type"text" v-model"firstName"> <br>名&am…

在VSCode中借助AI豐富C++Qt應用程序

隨著國內外各類自動化編程助手的普及&#xff0c;作為傳統桌面C開發者&#xff0c;也要及時地用上這樣強大的工具。考慮到網速問題&#xff0c;國外的服務時斷時續&#xff0c;還是傾向于使用一些國產的大語言模型助手。我們今天就來看看在VSCode下使用大語言模型輔助Qt開發。 …

Java八股文——JVM「內存模型篇」

JVM的內存模型介紹一下 面試官您好&#xff0c;您問的“JVM內存模型”&#xff0c;這是一個非常核心的問題。在Java技術體系中&#xff0c;這個術語通常可能指代兩個不同的概念&#xff1a;一個是JVM的運行時數據區&#xff0c;另一個是Java內存模型&#xff08;JMM&#xff0…

RabbitMQ 高可用與可靠性保障實現

RabbitMQ 高可用與可靠性保障實現詳解 一、高可用架構設計1.1 集群部署模式1.2 鏡像隊列&#xff08;Mirrored Queue&#xff09; 二、可靠性保障機制2.1 消息持久化2.2 確認機制&#xff08;Confirm & Ack&#xff09;2.3 死信隊列&#xff08;DLX&#xff09; 三、容災與…

12.7Swing控件6 JList

在 Java Swing 中&#xff0c;列表框&#xff08;JList&#xff09;是用于顯示一組選項的組件&#xff0c;用戶可以從中選擇一個或多個項目。以下是關于 Swing 列表框的詳細介紹&#xff1a; 1. 基本概念與用途 作用&#xff1a;以垂直列表形式展示選項&#xff0c;支持單選或…