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

windows c++ 程序的编译分析

 

本机环境 mingw64

  C:\mingw64\bin

卷 Windows 的文件夹 PATH 列表
卷序列号为 F023-2216
C:\MINGW64\BINaddr2line.exear.exeas.exec++.exec++filt.execc.execpp.exedlltool.exedllwrap.exeelfedit.exeg++.exegcc-ar.exegcc-nm.exegcc-ranlib.exegcc.exegcov-dump.exegcov-tool.exegcov.exegdb-add-indexgdb.exegdborig.exegdbserver.exegendef.exegenidl.exegenpeimg.exegfortran.exegprof.exegstackld.bfd.exeld.exelibatomic-1.dlllibgcc_s_seh-1.dlllibgfortran-5.dlllibgomp-1.dlllibquadmath-0.dlllibstdc++-6.dlllibwinpthread-1.dlllto-dump.exemingw32-make.exenm.exeobjcopy.exeobjdump.exeranlib.exereadelf.exesize.exestrings.exestrip.exewidl.exewindmc.exewindres.exex86_64-w64-mingw32-c++.exex86_64-w64-mingw32-g++.exex86_64-w64-mingw32-gcc-15.2.0.exex86_64-w64-mingw32-gcc-ar.exex86_64-w64-mingw32-gcc-nm.exex86_64-w64-mingw32-gcc-ranlib.exex86_64-w64-mingw32-gcc.exex86_64-w64-mingw32-gfortran.exe

 

他们的作用

GNU Binutils 是一系列的二进制工具的集合
主要  
ldI(Gld) GNU 链接器,有关链接的详细介绍请参见后文
as(Gas) GNU Assembler,通常称为gas或as,是由GNU项目开发的汇编程序。
GAS第一个版本的 在1986-1987年发布,由Dean Elsner编写,当时支持的是VAX架构
有关汇编的详细介绍
https://en.wikipedia.org/wiki/GNU_Assembler
 https://ee209-2019-spring.github.io/references/gnu-assembler.pdf (2.14版本)
 https://astro.uni-bonn.de/~sysstw/CompMan/gnu/as.html (1994年,你可以看到很多支持的其他架构)
 http://web.mit.edu/gnu/doc/html/as_1.html ( 这个手册是针对GNU assembler as的指南.)
 
 注意:
1)汇编器(Assembler)是将汇编语言翻译为机器语言的程序。一般而言,汇编生成的是目标代码,需要经gnu 链接器(ldl)生成可执行代码才可以执行
2) GAS,即 GNU 汇编器,是 GNU 操作系统的默认的汇编器。它不仅仅是支持x86架构,它适用于许多不同的体系结构并支持多种汇编语言语法。
   
3)默认是作为gcc后端工具来使用,也就是不是直接调用 as 命令来执行编译,是由其他工具来调用
4)默认语法是AT&T语法
5)支持两种基本注解 /**/ 和 #
   arm架构用 @作为注解
   i386架构,x86-64架构,mips架构,risc-v架构 等都采用 #
   AArch64架构采用 //
gold a new, faster, ELF only linker.
其他  
addr2line

用 来将程序 地址转 换成其所 对应的程 序源文 件及所对 应的代 码行,也可以得到所对应的函数。

ar

可以对静态库做创建、修改和提取的操作

1) windows static lib 以 .lib 为 后缀 的文 件 ,share lib 以 .dll 为 后缀
2)linux static lib 以 .a 为 后 缀 的 文 件 , share lib 以 .so 为 后 缀
   静 态 库 和 动 态 库 的 不 同 点 :
    1)static lib 的 代 码 在 编译 过 程 中 已 经 被 载 入 可 执 行 程 序 , 因 此 体 积 较 大 。 
    2)share lib 的 代 码 是 在 可 执行 程 序 运 行 时 才 载 入 内 存 的 

c++filt  反编译(反混淆,demangle)C++符号的工具
dlltool  创建创建Windows动态库
elfedit  
gprof  性能分析(profiling)工具程序
gprofng  
nlmconv  可以转换成NetWare Loadable Module(NLM)目标文件格式
nm  显示目标文件内的符号信息
objcopy

将一种对象文件翻译成另一种格式,譬如将.bin 转换成.elf、或者将.elf 转换成.bin 等。

objdump 主要的作用是反汇编。显示目标文件的相关信息
ranlib  产生静态库的索引
readelf 显示有关 ELF 文件的信息
size 列出可执行文件每个部分的尺寸和总尺寸,代码段、数据段、总大小等,请参见后文了解使用 size 的具体使用实例
strings  列出文件中可打印的字符串信息
strip  从目标文件中移除符号信息
windmc  Windows消息资源编译器
windres  Windows资源文件编译器
 ldd  可以用于查看一个可执行程序依赖的share lib。
 ld 它用于连接目标文件和库文件生成可执行文件或共享库文件。

一、简单的测试
1.g++ Test.cpp
  生成默认为a.exe的文件,这个过程包含了编译和链接。但是直接会忽略

2. -o <输出的程序名称>
  例如: D:\dlltest\cjiajia\test>g++ -o t.exe test.cpp
 -o命令表示指定可执行文件的名称 ,gcc/g++命令是非常灵活的,你不指定输出的文件名的时候,默认生成的是a.exe文件。
  
二、c++四部曲
   编写测试文件

#include <iostream>
using namespace std;
static int t = 1;
#define T 888
typedef int s;int main()
{s i = 1;cout << T * i << endl;  return 0;
}

步骤一、预处理生成 .i 的文件

D:\dlltest\cjiajia\test>g++ -E test.cpp > test.i (或 g++ -E test.c -o test.i)
   (-E 表示预处理阶段结束后停止,以便我们更好的分析 生成的test.i文件)

 D:\dlltest\cjiajia\test 的目录2025/12/07  17:33    <DIR>          .
2025/12/07  15:53    <DIR>          ..
2025/12/07  15:47               164 test.cpp
2025/12/07  15:50         1,049,399 test.i
2025/12/07  15:39               440 test2.cpp
2025/12/07  17:33             1,847 说明.txt5 个文件      1,053,226 字节2 个目录 601,594,114,048 可用字节
test.i如下:
# 0 "test.cpp" # 0 "<built-in>" # 0 "<command-line>" # 1 "test.cpp" # 1 "C:/mingw64/lib/gcc/x86_64-w64-mingw32/15.2.0/include/c++/iostream" 1 3 # 40 "C:/mingw64/lib/gcc/x86_64-w64-mingw32/15.2.0/include/c++/iostream" 3 # 1 "C:/mingw64/lib/gcc/x86_64-w64-mingw32/15.2.0/include/c++/bits/requires_hosted.h" 1 3 # 31 "C:/mingw64/lib/gcc/x86_64-w64-mingw32/15.2.0/include/c++/bits/requires_hosted.h" 3 # 1 "C:/mingw64/lib/gcc/x86_64-w64-mingw32/15.2.0/include/c++/x86_64-w64-mingw32/bits/c++config.h" 1 3 # 37 "C:/mingw64/lib/gcc/x86_64-w64-mingw32/15.2.0/include/c++/x86_64-w64-mingw32/bits/c++config.h" 3 #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wvariadic-macros"
...略...

步骤二、生成.s文件

预处理后的代码.i文件 被编译成汇编语言,生成 .s 文件(汇编代码)
使用的是as程序
D:\dlltest\cjiajia\test>g++ -S test.cpp
根据.i 文件, 生成.s文件D:\dlltest\cjiajia\test>dir驱动器 D 中的卷没有标签。卷的序列号是 7C23-817ED:\dlltest\cjiajia\test 的目录2025/12/07  17:33    <DIR>          .
2025/12/07  15:53    <DIR>          ..
2025/12/07  15:47               164 test.cpp
2025/12/07  15:50         1,049,399 test.i
2025/12/07  17:33             1,376 test.s
2025/12/07  15:39               440 test2.cpp
2025/12/07  17:33             1,847 说明.txt5 个文件      1,053,226 字节2 个目录 601,594,114,048 可用字节

test.s文件如下

.file "test.cpp"
.text
.data
.align 4
_ZL1t:
.long 1
.text
.globl main
.def main; .scl 2; .type 32; .endef
.seh_proc main

....略.....

步骤 3: 汇编 (Assembly)

汇编器将汇编代码转换为机器码,生成 .o 文件(目标文件)。
D:\dlltest\cjiajia\test>g++ -c test.cppD:\dlltest\cjiajia\test>dir驱动器 D 中的卷没有标签。卷的序列号是 7C23-817ED:\dlltest\cjiajia\test 的目录2025/12/07  17:38    <DIR>          .
2025/12/07  15:53    <DIR>          ..
2025/12/07  15:47               164 test.cpp
2025/12/07  15:50         1,049,399 test.i
2025/12/07  17:38             1,581 test.o
2025/12/07  17:37             1,376 test.s
2025/12/07  15:39               440 test2.cpp
2025/12/07  17:33             1,847 说明.txt6 个文件      1,054,807 字节2 个目录 601,594,109,952 可用字节

步骤 4: 链接 (Linking)

ld负责将多个目标文件及库文件链接在一起,生成最终的可执行文件(Windows上为 .exe,Linux上为 .out)。
D:\dlltest\cjiajia\test>g++ test.o -o test.exe (也可执行g++ test.o ,默认生成a.exe,linux 一般是.out文件)
#-o为指定生成的可执行程序的名称 D:\dlltest\cjiajia\test
>dir驱动器 D 中的卷没有标签。卷的序列号是 7C23-817ED:\dlltest\cjiajia\test 的目录2025/12/07 17:41 <DIR> . 2025/12/07 15:53 <DIR> .. 2025/12/07 15:47 164 test.cpp 2025/12/07 17:41 54,589 test.exe 2025/12/07 15:50 1,049,399 test.i 2025/12/07 17:38 1,581 test.o 2025/12/07 17:37 1,376 test.s 2025/12/07 15:39 440 test2.cpp 2025/12/07 17:39 1,847 说明.txt7 个文件 1,109,396 字节2 个目录 601,594,048,512 可用字节D:\dlltest\cjiajia\test>test 888

我们看到他的过程和c语言的编译过程是一样的,请参看 汇编的教程(四)- c程序的编译四个过程 - jinzi - 博客园

 

 

一步到位
 你完全可以一步到位,执行 g++ test.cpp 直接生成a.exe

D:\dlltest\cjiajia\test>g++ test.cpp
他会产生一个a.exe ,直接就可


或通过-o 指定生成文件名称  g++ -o mytest.exe  test.cpp 

D:\dlltest\cjiajia\test3>g++ -o mytest.exe  test.cpp
他会在当前目录下生成由-o指定的mytest.exe

 

三、复杂点的
   需要把相关目录都创建好,否则会出现问题

project/
|-bin
|-includefoo.h
|-lib|-all|-shared|-static
|-srcfoo1.cppfoo2.cppmain.cpp

  // foo.h

#ifndef TEST#define TESTint getnum();void sayhello();
#endif

 

源文件有两个版本

foo1.cpp   静态库 lib/foo.a
foo2.cpp 动态库lib /foo.so

源代码,这里foo1.cppfoo2.cpp都对头文件foo.h中的两个函数getnum()sayhello()分别进行了实现。

// foo1.cpp
#include "foo.h"
#include <iostream>int getnum(){return 1;
}void sayhello(){std::cout<<"hello,I am foo1\n";
}// foo2.cpp
#include "foo.h"
#include <iostream>int getnum(){return 2;
}void sayhello(){std::cout<<"hello,I am foo2\n";
}

我们将在main.cpp中引用头文件foo.h,用多种方式调用这个库 foo

// main.cpp
#include "foo.h"int main(){sayhello();return 0;
}

我们将在lib/static存在静态库,在lib/shared存放动态库,在lib/all存放动态库和静态库。

 1) windows 静态库 以 .lib 为 后缀 的文 件 ,动态库(共享) 以 .dll 为 后缀
 2)linux 静态库 以 .a 为 后 缀 的 文 件 , 动态库 以 .so 为 后 缀


1.静态库的编写

# 编译获得目标文件
g++ -c src/foo1.cpp -Iinclude -o lib/static/foo1.o# 打包得到.a静态库,注意前面是输出文件,后面是输入文件(可以有多个输入)
ar -crv lib/static/libfoo.a lib/static/foo1.o# 从lib/static复制一份到lib/all
cp lib/static/libfoo.a lib/all/libfoo.a

2.动态库的编写

# 注意在生成目标文件的时候需要加-fPIC选项,生成位置无关的目标文件
g++ -Iinclude -fPIC -c src/foo2.cpp -o lib/shared/foo2.o
# 注意得到动态库时,需要加-shared选项
g++ -shared lib/shared/foo2.o -o lib/shared/libfoo.so# 两步可以合并为一步,效果一样
g++ -fPIC -shared src/foo2.cpp -Iinclude -o lib/shared/libfoo.so# 从lib/shared复制一份到lib/all
cp lib/shared/libfoo.so lib/all/libfoo.so

注意:

  • 从目标文件到动态库文件,必须使用-shared选项
  • 从源文件到目标文件,建议使用-fPIC选项,可以生成位置无关的代码,此时动态库在内存中只需要加载一次,多个程序可以共同并且同时使用;否则只能相当于代码拷贝的方式,多个程序需要多次加载同一个动态库到内存中使用
  • 相比于静态库,动态库生成之后的存放位置是很重要的,因为可执行程序在运行时,还需要找到动态库并一起加载到内存中
  • 由于动态库通常有-fPIC,而静态库通常没有,因此动态库中如果想要链接一个静态库会报错,解决办法可以是把静态库也添加选项,改为生成位置无关的代码。

库的使用

首先,库的名称需要满足一定的命名规范,对于静态库通常命名为libxxx.a,对于动态库的名称通常为libxxx.so.x.y.z,还需要附带动态库的版本号。


  

http://www.jsqmd.com/news/65520/

相关文章:

  • AI元人文的奠基性架构:论“意义行为原生”理论与数字文明价值操作系统
  • 2025东莞精密模具厂家实力榜:宏良塑胶电子以高精度注塑技术领跑,六家本土技术代表企业核心优势深度解析
  • 三项神经突破变革机器人学习
  • 2025广东正达松远智能科技实力榜:给汤机与重力铸造自动化领跑,六家高潜力本土品牌深度解析
  • 2025 最新墙面艺术涂装服务商 / 厂家 TOP5 评测!技术创新 + 美学赋能权威榜单发布,重新定义空间装饰新体验,肌理壁膜 艺术漆 墙面艺术涂装 高端艺术漆
  • 深入解析:回溯剪枝的“减法艺术”:化解超时危机的 “救命稻草”(三)
  • 2025铁氟龙高温线厂家实力榜:明秀电子以极细线径技术领跑,六家高潜力本土品牌深度解析
  • Ubuntu 搜狗输入法安装
  • 图解IIS8上解决ASP.Net第一次访问慢的处理
  • 2025工业制冷设备实力榜:凯诺机械以高效节能技术领跑,六家国产冷水机厂家核心优势深度解析
  • 2025电热元件厂家实力榜:赫斯特(东莞)电热科技以创新热流道发热圈领跑,六大核心发热组件深度解析
  • 11 ORM关联表、事务
  • 11 ORM关联表、事务
  • python题库 No.28 shopping
  • 2025东莞中控自动化冲压机械手实力榜:六家国产高精度摆臂与二次元拉伸技术代表企业深度解析
  • 博客4
  • 【OPENGL ES 3.0 学习笔记】第十七天:模型矩阵、视图矩阵与投影矩阵 - 详解
  • 2025 AI 搜索品牌监测工具选型指南:主流系统推荐与排名洞察解决方案
  • 有名的汽配车间通风降温工业冷风机源头厂家,工厂降温车间/生产车间通风降温/敞开式车间通风降温/工厂车间降温通风工业冷风机厂家哪家好
  • 2025广东鉴正智能设备厂家实力榜:全自动电镀与龙门滚镀设备六家创新技术代表深度解析
  • 20
  • 2025自动提升机厂家实力排行榜:东莞垚林机械以智能高效技术领跑,六家创新本土品牌深度解析
  • Fibonacci 数列求余数和尾递归的一次实践
  • Fibonacci 数列求余数和尾递归的一次实践
  • 2025高压加速老化试验箱实力榜:东莞伟煌以创新热流仪技术领跑,六家国产精密设备厂商深度解析
  • opencv 学习: 05 像素处理
  • Linux驱动开发与Android驱动创建
  • 正则表达式匹配 IP 地址
  • 第十五节:对账详解
  • 2025铁氟龙制品厂家实力榜:东莞华氟绝缘材料以创新耐高温膜技术领跑,七类核心产品深度解析