当前位置: 首页 > news >正文

Linux----gcc、g++的使用以及一些问题

程序生成过程

在学习C语言的时候,我们知道,程序的生成需要经过预处理、编译、汇编、链接。

预处理

预处理时主要就是展开头文件、处理条件编译、删除注释、处理宏。我们来看一段代码(centos 7.6):

在这里直说了,用gcc/g++编译程序时,直接g++ 文件名,就会生成一个a.out的可执行文件,./a.out就可以执行它。但是现在我们要看预处理后的代码是怎样的,执行下面的指令会生code.i,他是预处理后的代码,如果不用-o并且重命名,那么会直接把预处理后的代码打印到终端:

用vim打开code.i观看预处理后的代码,这是代码头部:

这是到最后,可以看到多出来了一万多行代码,这都是展开的头文件,可以看到处理了宏定义,删除了注释,处理了条件编译:

编译

执行下面指令生成编译后的代码

vim打开,发现都是汇编语言。编译把预处理后的 C/C++ 源码转成 汇编代码。语法检查、优化都在这一步完成。输出是 .s 汇编文件。

汇编

虽然生成了.o目标文件,但是仍然还不能执行,为什么呢?因为虽然code.cpp变成了code.o,但是其中调用的一些库函数仍然找不到他们各自的定义。比如可能会调用printf,这时编译器只知道“有个叫 printf 的函数”,但没有它的地址。这些符号要等到 链接阶段 才能被解析并指向正确的库函数。

链接

此时执行如下链接指令生成可执行程序,并运行:

这里就牵扯到了一个问题,什么是库呢?

头文件中一般只有库函数的声明,而库函数的定义在库中。这些函数实现都在名为 libc.so.6 的库文件中,g++一般会到系统默认的搜索路径“/usr/lib”下进行查找,链接libc.so.6 库函数与.o文件,这样就能实现printf函数,这里的库有两种:静态库和动态库。那么如何进行链接?

静态库

一堆 .o 目标文件打包在一起(通常扩展名是 .a,Windows 下是 .lib)。在编译时,编译器会把需要的函数代码 直接拷贝 到可执行程序里。可执行文件体积大(因为包含了库的代码)。程序运行时不依赖外部库文件。更新库时,用到了该库的程序都需要重新编译程序。
静态库像是 把工具书的内容直接复印到你的作业里,你交出去的作业自己就全了,不需要再带工具书。

动态库

也是一堆函数的二进制代码,但在运行时才被加载(Linux 下 .so,Windows 下 .dll)。可执行文件里只保存“引用”,程序启动或运行时再从系统里找到对应的库。可执行文件体积小(只存符号引用)。多个程序可以共享同一个库,节省内存。更新库文件时,不用重新编译程序,只要接口没变,程序就能用新的功能。
动态库像是 写作业时引用一本公共图书馆的工具书,你的作业本身不包含解释,但只要图书馆有这本书,就能看懂。那么当链接时链接的是动态库的话就是动态链接,反之就是静态链接。

动态链接

g++一般默认是动态链接,ldd 显示的是程序运行时需要加载的动态库,以及它们在系统里的位置,查看刚刚生成的code:

静态链接

可以用指令要求静态链接,前提是有静态库文件,可以用指令下载g++与gcc的静态库:sudo yum install glibc-static libstdc++-static。紧接着使用-static选项要求静态链接,可以看到静态链接生成的可执行文件大小特别大。

如果不指定的话,一般是动态链接优先,如果没有动态库,会调用静态库进行静态链接。

对比总结

特性静态库 .a/.lib动态库 .so/.dll
链接时间链接时拷贝进可执行文件中运行时到对应库加载
可执行文件大小大(包含库代码)小(只保存引用)
运行依赖不依赖外部库依赖库文件存在
更新维护改库需重新编译更新库即可
内存占用每个程序有自己的副本多个程序共享一份

静态库:编译时打包进程序,独立但臃肿;动态库=运行时加载,共享但有依赖。

release与debug版本

可执行文件一般在发布时是release版本,程序在开发时是debug版本,形成可执行文件时添加了debug信息。默认情况下,gcc/g++ 编译出来的程序既不是严格的 Debug,也不是严格的 Release,可以理解为一个 未优化的普通构建。它只是编译器直接把源代码翻译成机器码生成可执行文件,适合快速测试和开发。

产生debug版本指令:

debug版本下因为添加了debug信息,所以要比默认的大一些。

release版本:

g++ code.cpp -O2 -DNDEBUG -o code_release
strip code_release   # 可选,去掉符号表,减小体积

参数说明

  • -O2 → 优化编译,平衡性能和编译时间。消除冗余代码、循环优化内联函数等

  • -O3 → 更激进优化,可选。函数内联扩展等

  • -DNDEBUG → 禁用 assert() 断言

  • -o code_release → 输出文件名

  • strip → 删除符号表(删除调试信息),让可执行文件更小,但不影响执行。

Release 版本 优化执行速度,不保留调试信息,Debug 版本则相反,保留调试信息、不开优化。观察文件大小:

http://www.dtcms.com/a/410856.html

相关文章:

  • 零基础软件设计师专栏计划
  • 插座工程量-图形识别轻松计量
  • IEEE TGRS 2025 | 突破小波U-Net局限,ASCNet实现更精准的红外去条纹!
  • 【每日一问】电气间隙和爬电距离有什么区别?
  • 网站邮件功能设计理论企业销售网站
  • 使用bert或roberta模型做分类训练时,分类数据不平衡时,可以采取哪些优化的措施
  • c语言网站上海有哪些企业
  • 网站搭建后提示建设中怎么申请自己公司的邮箱
  • 网站如何报备诚信经营网站的建设
  • CST微波混频电路 --- 频线任务,谐波平衡(Harmonic Balance)
  • 第 7 篇 Dify 应用介绍 + 聊天助手Agent 应用关键点说明
  • ajax与jQuery是什么关系?
  • 安装Latex环境与编辑器方法
  • 3DGS输入的三个bin文件的作用
  • 现在建设校园网站用什么软件培训加盟
  • 网站建设注意的问题如何更新网站
  • 计算机视觉 - 物体检测(二)单阶段:YOLO系列 + SSD
  • Oracle sql tuning guide 翻译 Part 6-3 --- 用Hint影响优化器
  • 网站设计建议成都软件外包公司
  • 免费网站注册申请自己的网站
  • 鸿蒙Next Asset Store Kit:打造关键资产的铜墙铁壁
  • count down 84 days
  • STM32CubeMX笔记(11)-- AD模块使用
  • commons-exec
  • 网页.网站.主页.网址.域名有什么联系深圳网站优化教程
  • 【LeetCode】51. N 皇后
  • 网站建设 上海浦东网络信息安全网站开发教程
  • 湖州网站建设2023设计院裁员惨烈程度
  • 论文《Inference for Iterated GMM Under Misspecification》的例子2
  • 5G RedCap模组应用领域分析