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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈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;支持单选或…