C++编译流程
编译器其实就是一个翻译器,把我们的文件内容翻译成机器能够看懂的指令,但如何合理翻译是核心。
C语言编译
需要经过以下几步:
- 词法分析:扫描代码,确定单词类型,比如是变量还是函数,是标识符还是运算符等等,这样操作后每个token都有自己的性质
- 语法分析:根据语法规则构建分析树
- 语义分析:主要是检查代码里是否有语义错误,比如函数返回值是否一致/是否访问超出作用域的变量/变量函数是否已经声明等
- 生成中间代码
- 汇编器生成目标机器语言
C++编译流程
预处理
将一些预处理指令的东西进行处理,比如#include、#pragma #define
对于include而言,预处理器会直接打开这个文件,然后将其copy进我们的cpp文件里。 (宏是直接进行字符串替换的)
此时生成的文件是.i文件
编译
通过编译器和汇编器将.cpp文件编译成.o文件,这里的.o其实就是一些01码,为了方便理解,可以先让编译器输出汇编指令(其实本质都是差不多的,做过CPU的应该知道汇编转01码怎么做)
换句话说,如果代码没有语法错误,编译是不应该报错的,比如缺少main函数入口等
// MyClass.cppclass MyClass {
public:int value;void setValue(int v) {value = v;helper(); // 调用自己的成员函数}void helper() {// 空函数,只为了演示调用过程}
};
实际编译后.o:
[ MyClass.o ] ←←←←← 编译器输出
┌──────────────────────────────┐
│ .text 段 │←─ 代码段(真正的机器码存放区)
│ │
│ 0x0000: MyClass::helper() │←─ helper 的汇编已生成在此位置
│ push rbp │
│ mov rsp, rbp │
│ ... │
│ ret │
│ │
│ 0x0040: MyClass::setValue() │←─ setValue 的汇编在这里
│ mov [this], v │
│ call helper() │←─ 这条 call 指令地址还没填
└──────────────────────────────┘┌──────────────────────────────┐
│ 符号表(.symtab) │←─ 存储函数名、地址、段类型等元信息
│ │
│ _ZN7MyClass6helperEv → 0x0000 ← helper() 的地址
│ _ZN7MyClass8setValueEi → 0x0040 ← setValue() 的地址
└──────────────────────────────┘
附上如何只编译文件+看汇编结果
g++ -c -O0 -fno-inline -o main.o main.cppobjdump -d main.o
需要注意的是,每个.o文件独立,函数留的地址也是相对地址,链接器还需要解决相对地址转绝对地址的问题。
链接
那么问题来了,如果我只有一个cpp文件,那么到编译这一步就可以了。但是在大型工程文件里,我们往往是有多个模块的,多个模块之间彼此还有调用关系,如何能生成正确的指令呢?其实就是依赖链接器,将多个cpp的.o文件给链接在一起。
多个模块之间的调用关系有:
- 你去访问别人的变量
- 调用别人的成员函数:在汇编指令中这一句话是call xxx,这个xxx就是函数签名
如果你在一个文件里声明并且定义了函数func,在另一个文件里也定义了func,对于include了这两个文件的文件来说,链接器不知道要链接具体哪一个,因此会报错称重复定义xxx。
举个具体的例子
MyClass.h代码:
class MyClass {
public:int value;void setValue(int v);void helper();
};
MyClass.cpp代码:
#include "MyClass.h"
void MyClass::setValue(int v) {value = v;helper();
}
void MyClass::helper() { }
main的cpp代码:
#include "MyClass.h"
int main() {MyClass obj;obj.setValue(42);return 0;
}
main的汇编:
0000000000000000 <main>:0: 55 push %rbp1: 48 89 e5 mov %rsp,%rbp4: 48 83 ec 30 sub $0x30,%rsp8: e8 00 00 00 00 callq d <main+0xd>d: 48 8d 45 fc lea -0x4(%rbp),%rax11: ba 2a 00 00 00 mov $0x2a,%edx16: 48 89 c1 mov %rax,%rcx19: e8 00 00 00 00 callq 1e <main+0x1e>1e: b8 00 00 00 00 mov $0x0,%eax23: 48 83 c4 30 add $0x30,%rsp27: 5d pop %rbp28: c3 retq
0x08 | 构造初始化 |
---|---|
0x16 | 设置this指针 |
0x19 | 调用setValue |
编译器在生成这段机器码的时候,先写了一条机器指令,但是不知道setValue的地址,因此在e8后面跟的都是00000000。同时在.o的重定位表里添加记录:
偏移地址:0x19
类型:CALL
目标符号:_ZN7MyClass8setValueEi
myclass.o的汇编
0000000000000000 <_ZN7MyClass8setValueEi>:0: 55 push %rbp1: 48 89 e5 mov %rsp,%rbp4: 48 83 ec 20 sub $0x20,%rsp8: 48 89 4d 10 mov %rcx,0x10(%rbp)c: 89 55 18 mov %edx,0x18(%rbp)f: 48 8b 45 10 mov 0x10(%rbp),%rax13: 8b 55 18 mov 0x18(%rbp),%edx16: 89 10 mov %edx,(%rax)18: 48 8b 4d 10 mov 0x10(%rbp),%rcx1c: e8 07 00 00 00 callq 28 <_ZN7MyClass6helperEv>21: 90 nop22: 48 83 c4 20 add $0x20,%rsp26: 5d pop %rbp27: c3 retq 0000000000000028 <_ZN7MyClass6helperEv>:28: 55 push %rbp29: 48 89 e5 mov %rsp,%rbp2c: 48 89 4d 10 mov %rcx,0x10(%rbp)30: 90 nop31: 5d pop %rbp32: c3 retq 33: 90 nop34: 90 nop35: 90 nop36: 90 nop37: 90 nop38: 90 nop39: 90 nop3a: 90 nop3b: 90 nop3c: 90 nop3d: 90 nop3e: 90 nop3f: 90 nop
因此,在链接器处理.o时会读取每个.o文件的重定位表,当看到
main.o:offset 0x19 → CALL → _ZN7MyClass8setValueEi
记录时,就会查找所有.o文件中是否有这个定义的,然后获取它的地址,并且计算当前call指令的位置到这个地址的相对偏移。每个.o文件会有符号表,用来存储每个函数的入口地址,方便补地址
动态链接和静态链接
此前提到的都是静态链接,直接打包进可执行文件中。那什么是动态链接呢?动态链接就是在运行的时候将程序用到的函数、库从外部共享库中加载进来。
优势就是节省空间,只需要加载一份,可以共享。支持更新和修复,但是稳定性和独立性差,性能也不好
生成exe文件
链接需要为exe指明程序的入口位置,这也就是main的作用
相关文章:
C++编译流程
编译器其实就是一个翻译器,把我们的文件内容翻译成机器能够看懂的指令,但如何合理翻译是核心。 C语言编译 需要经过以下几步: 词法分析:扫描代码,确定单词类型,比如是变量还是函数,是标识符还…...
人工智能:企业RAG方案
一、LangChain FAISS、Milvus / Weaviate介绍 在企业 RAG (Retrieval-Augmented Generation)方案中,LangChain FAISS 和 Milvus / Weaviate 都是用于向量检索(Vector Search)的核心工具。两者的核心区别在于 存储方…...
【Git流程最佳实践】 开发较大功能时应使用project branch
目录 背景和失败经验名词定义曾经使用project branch犯的错 建立project branch的必要性正确的使用project branch的方法 背景和失败经验 我们曾经使用过project branch,但是后来放弃了 名词定义 特性branch(特性分支): 在开发跨越新特性的时候会从主…...
线程的概念
目录 线程的概念 创建线程快速验证 物理内存管理 再谈页表 今天我们学习线程的概念 线程的概念 进程是一个指向起来的程序,进程内核数据结构代码和数据,线程称为指向流,执行粒度比进程要更细,是进程内部的一个执行分支&…...
firefly经典蓝牙和QProcess、QFileSystemWatcher记录
QProcess 默认不会启动一个 shell 来解析命令,而是直接调用操作系统的系统调用来启动外部程序。也就是通过fork一个子线程或者exec一个子进程来执行命令。 QProcess的参数模式 QProcess 需要明确指定命令的可执行文件路径或参数列表。 如果命令是一个可执行文件的路径…...
北斗设备启动流程与时长解析
北斗卫星导航系统作为我国自主研发的全球卫星导航系统,广泛应用于交通、通信、农业等多个领域。今天,我们就来详细探讨一下北斗设备的启动流程以及不同启动方式下的时长。 一、北斗设备的启动流程 北斗设备的启动流程可以分为以下几个关键步骤…...
PyTorch分布式训练中各节点如何通信
深度学习 文章目录 深度学习前言pytorch如何初始化分布式训练怎么知道要使用哪几台机器进行训练的如何根据标识进行初始化(init_method)如何获取进程的唯一标识rank如何实现数据如何分发 前言 同学们在处理分布式训练时经常会遇到以下几个疑问ÿ…...
又双叒叕Scrapy爬虫相关的面试题及详细解答
Scrapy是Python开发的一个快速、高层次的网络爬虫框架,专注于高效抓取网页并提取结构化数据。其核心设计基于异步处理机制,适合大规模数据采集任务。 文章目录 基础概念1. Scrapy框架的核心组件有哪些?架构与流程2. 描述Scrapy的工作流程核心组件详解3. 如何自定义Item Pipe…...
Docker与K8S是什么该怎么选?
用了很久的容器化,最近突然看到一个问题问: docker和K8S究竟有什么区别,到底该怎么选?我认真思考了一会,发现一时间还真说不明白,于是就研究了一段时间发布今天的博文! Docker vs Kubernetes&a…...
FPGA中串行执行方式之计数器控制
FPGA中串行执行方式之计数器控制 使用计数器控制的方式实现状态机是一种简单且直观的方法。它通过计数器的值来控制状态的变化,从而实现顺序逻辑。计数器的方式特别适合状态较少且状态转移是固定的场景。 基本原理 计数器控制的状态机 例程1:简单的顺序状态机 以下是一个…...
尝试使用tauri2+Django+React的项目
前言 使用Tauri2前端,本质是进程间的通信。并非前后端。 而想使用nw,先后端打包exe,再和前端打包成exe,并没有完成成功。 而笔者从Tauri中看到这种可能性。很有可能成功基于SeaORMMySQLTauri2ViteReact等的CRUD交互项目-CSDN博…...
用@keyframes-animation来实现动画效果
一、使用规则 keyframes 用于定义动画的关键帧。 animation属性 用于将keyframes动画用于元素上。 二、基本语法 keyframes keyframes xuanZhuan { /*xuanZhuan是动画名字,实现旋转*/0%{transform: rotate(0deg);}50%{transform: rotate(180deg);}100%{transform: rotate(…...
kernel中外部传递参数使用方法
在 Linux 内核模块开发中,module_param(rpc_tdebug, uint, 0600); 表示定义一个可通过外部传递参数进行配置的模块级变量,具体解析如下: 参数名称 rpc_tdebug 是模块参数的变量名,该变量需在代码中提前声明为静态全局变量&…...
AI赋能流域生态评估:从多源数据融合到服务价值预测的技术突破
流域生态系统服务评价是生态学与地理信息科学的交叉前沿,传统方法受限于数据碎片化与模型解释力不足。本文以随机森林-时空图卷积联合模型(RF-STGCN)为核心,结合2022年长江中游实际监测数据,详解AI技术在服务评价中…...
SZU软件工程大学生涯 2022~2026
用于个人面试前自我介绍,防止忘记或谈吐不流利。 面试官您好,我是来自深圳大学计算机与软件学院的软件工程专业的王雅贤。在校期间,我修读了程序设计基础、面向对象程序设计、数据结构、算法分析与设计、操作系统等核心课程,系统…...
如何设计一个合理的库存系统
库存管理系统是电商、供应链管理、仓储管理等核心系统之一。一个合理的库存系统需要同时满足高并发、数据一致性、实时性、扩展性等要求,以确保在各种业务场景下都能稳定运行。 本文将探讨如何设计一个合理的库存系统,包括库存模型设计、数据一致性策略…...
数据人的进阶之路:四年数仓实践与成长思考
前言 在数据仓库开发的过程中,常常会遇到很多值得思考的问题,它们不仅关乎技术的深度,也涉及业务理解、个人的成长,甚至是数据行业未来的价值。回顾过去的经历,有很多问题反复出现,甚至成为绕不开的课题&am…...
数据库原理及应用mysql版陈业斌实验一
🏝️专栏:Mysql_猫咪-9527的博客-CSDN博客 🌅主页:猫咪-9527-CSDN博客 “欲穷千里目,更上一层楼。会当凌绝顶,一览众山小。” 目录 实验一:数据库与数据表的定义和数据操作 1.实验数据如下 …...
Linux环境变量:深入解析与实用指南
目录 一、环境变量概述 二、环境变量的作用 三、环境变量的类型 3.1系统环境变量 3.2用户环境变量 四、环境变量的操作 4.1查看环境变量 4.2设置环境变量 4.3删除环境变量 五、环境变量的配置文件 六、环境变量的最佳实践 七、总结 环境变量是Linux系统中至关重要的…...
大数据 Spark 技术简介
Apache Spark 是一种快速、通用、可扩展的大数据处理引擎,最初由加州大学伯克利分校开发。它提供了一种高效的数据处理框架,可以处理大规模数据集,并在分布式计算集群上进行并行处理。 Apache Spark 的基本概念包括以下几个要点:…...
Go语言的基础类型
一基础数据类型 一、布尔型(Bool) 定义:表示逻辑真 / 假,仅有两个值:true 和 false内存占用:1 字节使用场景:条件判断、逻辑运算 二、数值型(Numeric) 1. 整数类型&…...
面试复习-基础网络+运维知识
一、TCP/IP模型及每层对应通信协议 1.1第一层-应用层 作用:服务及应用程序 HTTP --- 超文本传输协议--- 获取网页信息---80(TCP 80) HTTPS --- HTTP SSL(安全传输协议)/TLS ---443(TCP 443) …...
大屏设计新纪元:定制视觉盛宴
当城市天际线的巨型LED幕墙与元宇宙中的虚拟场景无缝交织,当博物馆的数字藏品在8K曲面屏上焕发新生,一个属于大屏设计的全新纪元已悄然降临。这场视觉革命不仅重构了信息传播的维度,更将“定制化体验”推向了前所未有的高度——每一寸屏幕都成…...
JavaIO流的使用和修饰器模式(直击心灵版)
系列文章目录 JavaIO流的使用和修饰器模式 文章目录 系列文章目录前言一、字节流: 1.FileInputStream(读取文件)2.FileOutputStream(写入文件) 二、字符流: 1..基础字符流:2.处理流:3.对象处理流:4.转换流: 三、修饰器…...
10-STL、位运算、常用函数库
1-STL vector vector是变长数组 //定义vector vector<int>a;//第一维长233,第二维长度动态变化 vector<int>b[233];//自定义的结构体类型也可以保存在vector中 struct res{...}; vector<rec>c;//函数 a.size();//返回vector的实际长度…...
【Ratis】Ratis Streaming概览
看了Tsz-Wo Nicholas Sze博士的一个关于Ratis的share,在share里提到了raits做的一个性能优化:客户端流。比较感兴趣,特此记录一下。如果想看原始分享的,可以搜关键词:Apache Ratis - A High Performance Raft Library 关于Ratis Stream的pdf介绍,在这个PR的附件里: [Ra…...
Python Seaborn面试题及参考答案
目录 如何用 stripplot () 绘制带随机偏移的分类散点图?如何控制 jitter 参数? swarmplot () 如何避免散点重叠?适用场景与数据量限制是什么? 使用 catplot () 绘制箱线图时,如何通过 kind 参数切换图表类型? 如何通过 hue 参数在分类图中添加第三个维度(如性别)? …...
linux下基本命令和扩展命令(安装和登录命令、文件处理命令、系统管理相关命令、网络操作命令、系统安全相关命令、其他命令)欢迎补充噢
基本命令 ls: 列出目录内容 ls:列出当前目录内容ls -l:以长格式列出(显示详细信息)ls -a:显示隐藏文件ls -lh:以易读格式显示文件大小 pwd: 显示当前工作目录 pwd:显示当前目录的绝对路径 cd:…...
K8S学习之基础四十:K8S配置altermanager发送告警到钉钉群
配置altermanager发送告警到钉钉群 创建钉钉群,设置机器人助手(必须是管理员才能设置),获取webhook webhook: https://oapi.dingtalk.com/robot/send?access_token25bed933a52d69f192347b5be4b2193bc0b257a6d9ae68d81619e3ae3d93f7c6…...
实用工具--OfficeAI 助手 v0.3.20(长期免费,2025-03-18 本地支持WPSWord联动)
软件简介 OfficeAI助手,作为Microsoft Office与WPS的得力智能插件,集文档自动生成、内容精准校对与润色、公式智能推荐等多功能于一体。它凭借强大的数据分析能力,深度融入Office/WPS办公生态,一键简化复杂流程,让办公…...
Android 关于compose的一些坑和理解
** 1.如何在 WindowManager.addView 中使用 Jetpack Compose** 一、引出问题 Android 开发中,很常见的一个场景,通过 WindowManager.addView() 添加一个 View 到屏幕上。Android 最新的视图框架 Jetpack Compose,如何应用进来。这个被添加的…...
ref setState 合成事件
ref & setState & 合成事件 受控组件的概念:数据改变视图的叫受控组件;通过dom操作改变的叫非受控。 语法:给refxxx赋一个值,然后通过this.refs.xxx就可以获取到相应dom元素,通过你这个名字存储的值就是这个do…...
调用feapder作为子程序时setting.py文件不起作用
feaper 官方文档地址: 简介及安装 - feapder官方文档|feapder-document 问题: 在最近的开发中需要调用feapder作为主程序调用的子程序时发现自动入库时无法入库,通过查看日志信息发现连接数据库时被拒绝连接了,但是我的setting.p…...
gralloc1_perform具体在干什么
gralloc1_perform 会在特定场景下通过 ioctl 调用,执行 缓存 (cache) 管理 和 内存映射 操作,确保 CPU 和 GPU 之间的数据一致性。 📌 为什么需要对 cache 进行操作? 在 Android 系统中,CPU 和 GPU 通常共享 DDR 内存…...
【Pandas】pandas Series plot.barh
Pandas2.2 Series Plotting 方法描述Series.plot([kind, ax, figsize, …])用于绘制 Series 对象的数据可视化图表Series.plot.area([x, y, stacked])用于绘制堆叠面积图(Stacked Area Plot)Series.plot.bar([x, y])用于绘制垂直条形图(Ver…...
机器学习之浅层神经网络
文章目录 一、浅层神经网络概述(一)定义(二)常见类型 二、浅层神经网络的前向传播三、浅层神经网络的反向传播四、编写浅层神经网络案例(Python NumPy 实现)代码解释 五、浅层神经网络与深度学习的区别&am…...
透析Vue的nextTick原理
nextTick 是 Vue.js 中的一个核心机制,用于在 下一次 DOM 更新周期后 执行回调函数。它的核心原理是 利用 JavaScript 的事件循环机制(Event Loop),结合微任务(Microtask)或宏任务(Macrotask&am…...
Beans模块之工厂模块注解模块@Qualifier
博主介绍:✌全网粉丝5W,全栈开发工程师,从事多年软件开发,在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建与毕业项目实战,博主也曾写过优秀论文,查重率极低,在这方面有丰富的经验…...
产品更新 | 数字助决胜:华望M-Arch平台实现从体系模型到仿真推演
华望产品更新速递 功能介绍 |M-Arch体系建模软件的核心功能 ◆体系架构建模 ◆逻辑仿真 ◆与多种工具集成 ◆多专业协同建模 产品亮点 |M-Arch软件在体系作战中的作用 ◆全面构建任务和体系架构建模的能力 ◆模型化的装备体系分析方法 ◆提升作战体系架构设计与优化 前…...
IP地址结构体与字符串转换函数详解
IP地址结构体与字符串转换函数详解 在Linux C网络编程中,IP地址的二进制结构体(如struct in_addr)与字符串形式(如"192.168.1.1")之间的转换经常涉及到,与IP地址格式相关的函数包括inet_aton、i…...
debug - 安装.msi时,为所有用户安装程序
文章目录 debug - 安装.msi时,为所有用户安装程序概述笔记试试在目标.msi后面直接加参数的测试 备注备注END debug - 安装.msi时,为所有用户安装程序 概述 为了测试,装了一个test.msi. 安装时,只有安装路径的选择,没…...
基于springboot的社区团购系统(012)
摘 要 本课题是根据用户的需要以及网络的优势建立的一个社区团购系统,来满足用户团购的需求。 本社区团购系统应用Java技术,MYSQL数据库存储数据,基于Spring Boot框架开发。在网站的整个开发过程中,首先对系统进行了需求分析&…...
应用权限组列表
文章目录 使用须知位置相机麦克风通讯录日历运动数据身体传感器图片和视频音乐和音频跨应用关联设备发现和连接剪切板文件夹文件(deprecated) 使用须知 在申请目标权限前,建议开发者先阅读应用权限管控概述-权限组和子权限,了解相关概念,再合…...
4.1、网络安全模型
目录 网络安全体系概述网络安全模型-BLP模型网络安全模型-Biba模型网络安全模型 - 信息流模型信息保障模型能力成熟度模型其它安全模型网络安全原则 网络安全体系概述 网络安全体系是网络安全保证系统的最高层概念抽象,是一个体系,体系一般是一个概念&a…...
前端对接生成式AI接口(类ChatGPT)问题汇总
文章目录 前端实现对话流问题总结流式数据传输问题后台Response Headers问题大量数据分段接收问题多个流时间戳(Time)相同导致被合并的问题 中止对话问题复制问题部署上线问题(Nginx缓冲导致) 前端实现对话流问题总结 流式数据传…...
布隆过滤器(Bloom Filter)详解
布隆过滤器详解 1. 什么是布隆过滤器? 布隆过滤器(Bloom Filter)是一种高效的概率型数据结构,主要用于判断某个元素是否存在于一个集合中。它的特点是: 允许误判:可能会误判元素存在(假阳性&…...
QoS(Quality of Service)服务质量概念
一、什么是QoS? QoS(Quality of Service)即服务质量,在网络业务中可以通过保证传输的带宽、降低传输时延、降低数据丢包率以及时延抖动等措施来提高服务质量。QoS是一套用于管理和提高网络性能的工具和技术,用于流量优…...
CSS实现当鼠标悬停在一个元素上时,另一个元素的样式发生变化的效果
CSS可以实现当鼠标悬停在一个元素上时,另一个元素的样式发生变化的效果。可以通过以下几种方法来实现: 1. 使用兄弟选择器(Adjacent Sibling Selector) 如果两个元素是兄弟关系(即它们有相同的父元素)&am…...
【C++11】左值引用、右值引用、移动语义和完美转发
🦄个人主页:修修修也 🎏所属专栏:C ⚙️操作环境:Visual Studio 2022 目录 📌左值引用和右值引用 🎏左值和左值引用 🎏右值和右值引用 📌左值引用和右值引用比较 🎏左值引用 🎏右值…...
Docker镜像迁移
目录 1.查看镜像当前配置 2.镜像迁移 1. 停止 Docker Desktop 2. 关闭 WSL 实例(若基于 WSL 2) 4. 导出原镜像数据 5.注销原实例 6. 导入数据到新路径 7. 设置 Docker Desktop 使用新路径(可选) 8. 启动 Docker Desktop …...