Linux中C/C++程序编译过程与动静态链接库概述

news2024/10/27 10:03:04


✨✨ 欢迎大家来访Srlua的博文(づ ̄3 ̄)づ╭
~✨✨

🌟🌟 欢迎各位亲爱的读者,感谢你们抽出宝贵的时间来阅读我的文章。

我是Srlua小谢,在这里我会分享我的知识和经验。🎥

希望在这里,我们能一起探索IT世界的奥妙,提升我们的技能。🔮

记得先点赞👍后阅读哦~ 👏👏

📘📚 所属专栏:嵌入式

欢迎访问我的主页:Srlua小谢 获取更多信息和资源。✨✨🌙🌙

​​

目录

C/C++程序开发与链接库概述

ldd

用法

示例

选项

注意事项

结论

C/C++ 程序开发过程中的四个主要步骤

1. 预处理 (Preprocessing)

2. 编译 (Compilation)

3. 汇编 (Assembly)

4. 链接 (Linking)

总结

动态链接库

动态库的特点

动态库的管理

结论

静态链接库

静态库的特点

结论

静态库与动态库的比较

在某些云服务器上,默认情况下可能没有安装 C/C++ 的静态库和相关的编译工具链。

1. Ubuntu/Debian 系统

2. CentOS/RHEL 系统

3. 验证安装

4. 编译静态库示例

结论

先有语言还是先有编译器

1. 早期的编程语言

2. 高级语言的出现

3. 编译器的开发

4. 自举过程

总结


C/C++程序开发与链接库概述

ldd

ldd 是 Linux 中的一个命令,用于显示一个可执行文件或共享库所依赖的共享库(动态链接库)。这个命令可以帮助开发者和系统管理员检查程序的动态链接依赖关系,确保所有必要的库都能找到,并且程序能够正常运行。

用法

基本语法如下:

ldd [选项] <可执行文件>

示例

  1. 查看依赖库

    ldd /path/to/your/executable
  2. 示例输出

    linux-vdso.so.1 =>  (0x00007ffcb7ff3000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007ffcb7e7e000)
    /lib64/ld-linux-x86-64.so.2 (0x00007ffcb81da000)
    

    这里的输出表示可执行文件依赖于 libc.so.6ld-linux-x86-64.so.2 等共享库。

选项

  • --version:显示版本信息。
  • --help:显示帮助信息。
  • --quiet:只输出错误信息。

注意事项

  • ldd 可能会执行被检查的程序,尤其是在处理不受信任的二进制文件时,可能会存在安全风险。
  • 对于静态编译的程序,ldd 不会返回任何库,因为这些程序不依赖于共享库。

结论

ldd 是一个非常实用的工具,可以帮助开发者和运维人员排查动态链接库的问题,确保程序的可移植性和兼容性。

C/C++ 程序开发过程中的四个主要步骤

1. 预处理 (Preprocessing)

描述: 在这个步骤中,编译器处理所有的预处理指令,例如宏定义、条件编译和头文件包含。它生成一个扩展后的源代码文件。

Bash 示例

gcc -E example.c -o example.i

实际例子: 假设有一个名为 example.c 的文件,内容如下:

#include <stdio.h>
#define PI 3.14

int main() {
    printf("Value of PI: %f\n", PI);
    return 0;
}

运行上述命令后,生成的 example.i 文件将包含所有的预处理指令处理结果,显示 #include 的内容以及宏 PI 的替换。

2. 编译 (Compilation)

描述: 在这个步骤中,编译器将预处理后的源代码转换为汇编语言。生成的文件通常以 .s 结尾。

Bash 示例

gcc -S example.i -o example.s

实际例子: 使用上一步生成的 example.i 文件,运行上述命令后,生成的 example.s 文件可能包含类似以下内容:

	.file	"example.c"
	.text
	.globl	main
	.type	main, @function
main:
	...

3. 汇编 (Assembly)

描述: 在这个步骤中,汇编器将汇编代码转换为机器代码,生成目标文件,通常以 .o.obj 结尾。

gcc -c example.s -o example.o

实际例子: 运行上述命令后,会生成 example.o 文件。这个文件包含了机器码,但不是一个完整的可执行程序。

4. 链接 (Linking)

描述: 在这个步骤中,链接器将目标文件与需要的库文件链接,生成最终的可执行文件。

Bash 示例

gcc example.o -o example

实际例子: 运行上述命令后,会生成名为 example 的可执行文件。你可以运行它:

./example

输出将是:

Value of PI: 3.140000

总结

以上步骤展示了从源代码到可执行文件的完整过程,每一步都可以使用 Bash 命令在 Linux 中执行。这些步骤的输出文件在整个编译过程中扮演着重要的角色,确保程序的最终执行能够顺利进行。

动态链接库

libc.so.6 是 Linux 系统中的标准 C 库的动态链接库(shared library)。动态库的主要特点是可以在运行时被程序加载和使用,而不是在编译时将库的代码直接嵌入到可执行文件中。这使得程序可以共享同一个库,节省内存并简化更新过程。

动态库的特点

  1. 文件格式:动态库的文件名通常以 .so(Shared Object)为后缀,例如 libc.so.6
  2. 共享性:多个程序可以共享同一个动态库,从而减少内存使用。
  3. 动态加载:程序在运行时可以动态加载库,支持插件式的开发。
  4. 版本控制:动态库支持版本控制,例如 libc.so.6 表示 C 标准库的一个具体版本。

动态库的管理

在 Linux 系统中,动态库通常存放在 /lib/usr/lib/usr/local/lib 目录下。可以使用 ldconfig 命令来更新动态库的缓存,以便系统能够找到新的库。

结论

libc.so.6 是 Linux 系统中标准 C 库的一个具体实现版本。动态库的使用不仅节省了内存资源,还使得程序的更新和维护变得更加方便。在开发中,创建和使用动态库是提高程序效率和模块化的关键技术。

静态链接库

静态链接库是在编译时将库的代码直接嵌入到可执行文件中,从而生成一个独立的可执行程序。静态库通常具有 .a 后缀(在 Linux 系统中),与动态链接库不同,静态链接库的代码在链接时就已经被复制到最终的可执行文件中,因此不需要在运行时依赖外部库。

静态库的特点

  1. 文件格式:静态库的文件通常以 .a 为后缀,例如 libmylib.a
  2. 自包含性:链接静态库的可执行文件在运行时不需要外部库,适合在没有共享库环境的系统中运行。
  3. 文件体积大:由于静态库的代码被复制到每个可执行文件中,程序体积通常比使用动态库的大。
  4. 更新困难:如果库的代码需要更新,需要重新编译所有使用该库的程序。

结论

静态链接库在需要自包含性和不依赖外部环境的场合非常有用。尽管其更新成本较高,但在某些嵌入式系统或分发时无法保证共享库一致性的场合,静态库依然是一个非常实用的选择。

静态库与动态库的比较

特点静态库动态库
文件后缀.a.so
内存使用高(每个程序都有一份库的代码)低(共享库的代码)
更新方便性需重新编译所有依赖的程序只需更新库文件
运行时依赖无(不需要库文件)需要库文件
文件体积较大较小

在某些云服务器上,默认情况下可能没有安装 C/C++ 的静态库和相关的编译工具链。

要在这样的环境中开发和编译 C/C++ 程序,您需要手动安装必要的工具和库。下面是一些常见的 Linux 发行版(如 Ubuntu 和 CentOS)上安装 C/C++ 编译器和静态库的步骤。

1. Ubuntu/Debian 系统

对于基于 Debian 的系统(如 Ubuntu),可以使用 apt 包管理器进行安装:

# 更新包列表
sudo apt update

# 安装 C 和 C++ 编译器
sudo apt install build-essential

# 安装静态库
sudo apt install libc6-dev
  • build-essential 包包括 GCC(GNU Compiler Collection)、G++ 和其他编译工具以及标准库的开发文件。
  • libc6-dev 提供了 C 标准库的头文件和静态库。

2. CentOS/RHEL 系统

对于基于 RHEL 的系统(如 CentOS),可以使用 yumdnf 包管理器进行安装:

# 更新包列表(可选)
sudo yum update

# 安装 C 和 C++ 编译器
sudo yum groupinstall "Development Tools"

# 安装静态库
sudo yum install glibc-devel
  • Development Tools 组包包含了 GCC、G++ 和其他开发工具。
  • glibc-devel 提供了 C 标准库的头文件和静态库。

3. 验证安装

安装完成后,可以通过以下命令验证 GCC 和 G++ 是否安装成功:

gcc --version
g++ --version

您应该能够看到安装的版本信息。

4. 编译静态库示例

一旦安装了编译工具,您可以按照以下步骤创建一个静态库:

  1. 创建源文件mathlib.c):
    #include <stdio.h>
    
    void print_sum(int a, int b) {
        printf("Sum: %d\n", a + b);
    }
    
  2. 编译源文件为目标文件
    gcc -c mathlib.c -o mathlib.o
    
  3. 创建静态库
    ar rcs libmathlib.a mathlib.o
    
  4. 使用静态库的程序main.c):
    #include <stdio.h>
    
    extern void print_sum(int, int);
    
    int main() {
        print_sum(3, 5);
        return 0;
    }
    
  5. 编译并链接
    gcc main.c -L. -lmathlib -o main
    
  6. 运行程序
    ./main
    

结论

在云服务器上,如果默认没有安装 C/C++ 的静态库和编译工具,您可以通过相应的包管理器手动安装所需的工具和库。安装完成后,您就可以开始编写和编译 C/C++ 程序了。

先有语言还是先有编译器

1. 早期的编程语言

  • 机器语言和汇编语言
    • 在计算机发展的早期阶段,程序员主要使用机器语言(以二进制或十六进制形式表示)进行编程。这种语言直接对应于计算机硬件,程序员必须理解底层架构。
    • 随后,汇编语言出现,它为机器语言提供了助记符,使得编写程序更加容易,但仍然与具体的硬件架构紧密相关。

2. 高级语言的出现

  • 第一代高级语言
    • 随着计算机技术的发展,出现了更高级的编程语言,例如 Fortran(1957 年)和 COBOL(1959 年)。这些语言允许程序员以更抽象的方式编写代码,不必关心底层的机器指令。

3. 编译器的开发

  • 编译器的实现
    • 为了将这些高级语言转换为机器代码,开发了编译器。编译器是一种特殊的软件工具,负责将程序员编写的源代码翻译成计算机能够理解的指令。
    • 最早的编译器通常是用汇编语言或其他低级语言编写的,这使得编译器与特定的硬件架构紧密相连。

4. 自举过程

  • 自举(Bootstrapping)
    • 一旦编译器开发出来,就可以使用它来编译其他程序,包括它自身的后续版本。这个过程称为自举。
    • 例如,最初的 C 编译器可能用汇编语言实现,随后用 C 语言重写,最后能够用自己编译自己。

总结

综上所述,计算机历史上是先有编程语言,再有编译器。编程语言的出现为编译器的发展提供了基础,而编译器则使得这些语言可以被计算机理解和执行。因此,编程语言和编译器的关系是相互依存的,语言的设计往往影响编译器的实现,而编译器的发展又会推动语言的演进。

​​

希望对你有帮助!加油!

若您认为本文内容有益,请不吝赐予赞同并订阅,以便持续接收有价值的信息。衷心感谢您的关注和支持!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2224587.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

qt QMainWindow详解

一、概述 QMainWindow继承自QWidget&#xff0c;并提供了一个预定义的布局&#xff0c;将窗口分成了菜单栏、工具栏、状态栏和中央部件区域。这些区域共同构成了一个功能丰富的主窗口&#xff0c;使得应用程序的开发更加简单和高效。 二、QMainWindow的常用组件及功能 菜单栏&…

【Java网络编程】从套接字(Socket)概念到UDP与TCP套接字编程

目录 网络编程 1.socket套接字 2.udp数据报套接字编程 DatagramSocket API DatagramPacket API Java基于UDP实现客户端-服务器代码实例 3.tcp流套接字编程 ServerSocket API Socket API TCP中的长短连接 Java基于TCP客户端-服务器代码实例 网络编程 1.socket套接字 S…

云对象存储进阶

《使用Minio搭建文件服务器》一文对minio作了简单的介绍&#xff0c;本文为进阶学习。 1.对象存储产品介绍 目前市场上流行各种对象存储服务&#xff0c;诸如以下&#xff1a; Amazon S3&#xff1a;亚马逊提供的服务&#xff0c; 是市场上最成熟的产品&#xff0c;拥有最大的…

ATom:2016-2018 年沿飞行轨迹的 CAM-chem/CESM2 模型输出

目录 简介 摘要 代码 引用 网址推荐 知识星球 机器学习 ATom: CAM-chem/CESM2 Model Outputs Along Flight Tracks, 2016-2018 ATom&#xff1a;2016-2018 年沿飞行轨迹的 CAM-chem/CESM2 模型输出 简介 该数据集包含沿 ATom 飞行轨迹的 CAM-chem&#xff08;带化学的…

[ARM-2D 专题]5 MDK编译器一个旧版本-Ofast优化bug的问题及解决办法

最近开始大量基于ARM-2D开发应用项目&#xff0c;为了达到最佳性能&#xff0c;我们使用了编译器的许多特殊技能&#xff0c;其中就包含了-Ofast优化&#xff0c;很不幸&#xff0c;一不小心踩坑了。 案发情况如下&#xff1a; 使用的MDK版本5.36&#xff0c;编译器6.16 优化选…

在GeoTools中的Shapefile属性表读取效率之Shp与Dbf对比

目录 前言 一、POI测试数据简介 1、选用的POI数据 2、关于数据的属性数据 二、属性数据读取的两种方式实现 1、基于DbaseFileReader的读取 2、基于SimpleFeatureSource的读取 三、实际运行对比 1、内存和CPU占用情况 2、运行耗时情况 四、总结 前言 众所周知&#x…

【深度学习中的注意力机制10】11种主流注意力机制112个创新研究paper+代码——交叉注意力(Cross-Attention)

【深度学习中的注意力机制10】11种主流注意力机制112个创新研究paper代码——交叉注意力&#xff08;Cross-Attention&#xff09; 【深度学习中的注意力机制10】11种主流注意力机制112个创新研究paper代码——交叉注意力&#xff08;Cross-Attention&#xff09; 文章目录 【…

‌Spring MVC的主要组件有哪些?

前言 SpringMVC的核心组件包括DispatcherServlet、Controller、HandlerMapping、HandlerAdapter、ViewResolver、ModelAndView等&#xff0c;它们协同工作以支持基于MVC架构的Web应用程序开发。这些组件使得开发人员能够以一种声明式和模块化的方式构建Web应用程序&#xff0c…

小程序开发实战:PDF转换为图片工具开发

目录 一、开发思路 1.1 申请微信小程序 1.2 编写后端接口 1.3 后端接口部署 1.4 微信小程序前端页面开发 1.5 运行效果 1.6 小程序部署上线 今天给大家分享小程序开发系列&#xff0c;PDF转换为图片工具的开发实战&#xff0c;感兴趣的朋友可以一起来学习一下&#xff01…

ECharts饼图-基础南丁格尔玫瑰图,附视频讲解与代码下载

引言&#xff1a; 在数据可视化的世界里&#xff0c;ECharts凭借其丰富的图表类型和强大的配置能力&#xff0c;成为了众多开发者的首选。今天&#xff0c;我将带大家一起实现一个饼图图表&#xff0c;通过该图表我们可以直观地展示和分析数据。此外&#xff0c;我还将提供详…

一、在cubemx下RTC配置调试实例测试

一、rtc的时钟有lse提供。 二、选择rtc唤醒与闹钟功能 内部参数介绍 闹钟配置 在配置时间时&#xff0c;注意将时间信息存储起来&#xff0c;防止复位后时间重新配置。 if(HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR0)! 0x55AA)//判断标志位是否配置过&#xff0c;没有则进…

qt EventFilter用途详解

一、概述 EventFilter是QObject类的一个事件过滤器&#xff0c;当使用installEventFilter方法为某个对象安装事件过滤器时&#xff0c;该对象的eventFilter函数就会被调用。通过重写eventFilter方法&#xff0c;开发者可以在事件处理过程中进行拦截和处理&#xff0c;实现对事…

WSL2 Ubuntu22.04编译安装LLVM

前提 这两天因为工作需要&#xff0c;要编译一个Debug版本的llvm。这里对编译安装过程进行一个简单的记录&#xff0c;同时也记录下这个过程中遇到的几个问题。 下载源码并编译 有关llvm编译安装的官方文档在这里。 从git仓库clone llvm的源码。 git clone https://github.c…

FPGA搭建PCIE3.0通信架构简单读写测试,基于XDMA中断模式,提供3套工程源码和技术支持

目录 1、前言工程概述免责声明 2、相关方案推荐我已有的PCIE方案本博客方案的PCIE2.0版本 3、PCIE基础知识4、工程详细设计方案工程设计原理框图XDMA配置及使用XDMA中断模块数据缓存架构用户逻辑Windows版本XDMA驱动安装Linux版本XDMA驱动安装测试应用程序工程源码架构PCIE上板…

电磁场-Laplace算子与冲激函数的关系

csdn重新打一遍公式太麻烦了。欢迎转到我的知乎账号上查阅原版文章&#xff0c;也可后台私信我发送原版PDF或者markdown。 电磁场-Laplace算子与冲激函数的关系 - 知乎 下面的文章是一张超大的图片。

论1+2+3+4+... = -1/12 的不同算法

我们熟知自然数全加和&#xff0c; 推导过程如下&#xff0c; 这个解法并不难&#xff0c;非常容易看懂&#xff0c;但是并不容易真正理解。正负交错和无穷项计算&#xff0c;只需要保持方程的形态&#xff0c;就可以“预知”结果。但是这到底说的是什么意思&#xff1f;比如和…

C++扑克牌(poker)2024年CSP-J认证第二轮第一题 CCF信息学奥赛C++ 中小学初级组 第二轮真题解析

目录 C扑克牌&#xff08;poker&#xff09; 一、题目要求 1、编程实现 2、输入输出 二、算法分析 三、程序编写 四、运行结果 五、考点分析 六、推荐资料 C扑克牌&#xff08;poker&#xff09; 2024年CSP-J认证第二轮第一题 一、题目要求 1、编程实现 小 P 从同学…

HarmonyOS 组件样式@Style 、 @Extend、自定义扩展(AttributeModifier、AttributeUpdater)

1. HarmonyOS Style 、 Extend、自定义扩展&#xff08;AttributeModifier、AttributeUpdater&#xff09; Styles装饰器&#xff1a;定义组件重用样式   ;Extend装饰器&#xff1a;定义扩展组件样式   自定义扩展&#xff1a;AttributeModifier、AttributeUpdater 1.1. 区…

HarmonyOS 5.0应用开发——应用打包HAP、HAR、HSP

【高心星出品】 目录 应用打包HAP、HAR、HSPModule类型HAPHAR创建HAR建立依赖HAR共享内容 HSP创建HSP建立依赖同上HSP共享内容同上 HAR VS HSP 应用打包HAP、HAR、HSP 一个应用通常会包含多种功能&#xff0c;将不同的功能特性按模块来划分和管理是一种良好的设计方式。在开发…

【哈工大_操作系统实验】Lab9 proc文件系统的实现

本节将更新哈工大《操作系统》课程第九个 Lab 实验 proc文件系统的实现。按照实验书要求&#xff0c;介绍了非常详细的实验操作流程&#xff0c;并提供了超级无敌详细的代码注释。 实验目的&#xff1a; 掌握虚拟文件系统的实现原理&#xff1b;实践文件、目录、文件系统等概念…