C++编译与链接

C++编译连接问题总结(cmake连接设置、环境变量设置查看、C++静态动态、软连接链接 一、静态动态 1.1 静态动态编译 --> 编译 --> 汇编 --> 链接 (1)预编译,即预处理,主要处理在源代码文件中以“#”开始的预编译指令,如宏展开、处理条件编译指令、处理#include指令等。 (2)编译过程就是把预处理完的文件进行一系列词法分析、语法分析、语义分析以及优化后生成相应的汇编代码文件。 (3)汇编是将汇编代码转变成二进制文件。 (4)链接将二进制文件链接成一个可执行的命令,主要是把分散的数据和代码收集并合成一个单一的可加载并可执行.. 阅读详情

编译

  • 编译过程
    首先,编译器会执行预处理,也就是所有以"#"开头的预处理语句。
    ->优化阶段->生成汇编并转换到机器语言->生成obj文件
    其中每个cpp文件都是单独的编译单元,都是独自生成相对的obj文件
    后期才通过linker进行相互的链接。

  • 预处理相关
    大致有#include:单纯的将头文件内的所有文本复制到所在的位置。
    #define:单纯的文本替换。
    #if:进行条件判断,若满足条件,则if所包含的文本有效,反之则无效。
    预处理相关设置:
    1 生成预处理后的文件,但不能生成obj生成预处理后的文件
    2 生成汇编代码文件在这里插入图片描述
    3 设置优化级数,使生成的obj、asm等文件不包含优化代码
    在这里插入图片描述
    优化等级与runtime check挂钩在这里插入图片描述

链接

  • 链接过程:

首先,要理解链接是将多个obj文件链接为一个exe文件,并解决在某个文件中引用另一个文件中的符号相关的问题。
链接时,linker首先决定各个obj文件在最终exe文件中的位置,然后访问所有obj文件的地址表,将其全部地址进行重定向,然后遍历所有obj文件中未解决的符号,生成未解决符号表,并在符号表中查找匹配的符号,将未解决符号表填补完成,最后对每个obj文件进行排序即完成。

  • 链接方式:
    1 静态链接:在链接时,就查找obj中缺失的目标函数,再去静态库中查找相应的obj对象,直接包含在程序内,运行时不用再次查询。但这里在库中查找的obj对象是一整个,也就是说即使只使用了它其中一个函数,还是会包含obj中其他所有的函数,导致内存大量浪费;且每次更新库,都需要将库重新编译并链接一遍。但优点在于运行时不用查询,运行速度快。
    2 动态链接:在运行时,检测到未解决符号,再去查找包含相应符号的obj文件,并且一个obj只用加载一次,空间使用率高,且更新时不用再次编译链接。但运行速度比不上静态库。
    下面是动态链接的过程:
    假设现在有两个程序program1.o和program2.o,这两者共用同一个库lib.o,假设首先运行程序program1,系统首先加载program1.o,当系统发现program1.o中用到了lib.o,即program1.o依赖于lib.o,那么系统接着加载lib.o,如果program1.o和lib.o还依赖于其他目标文件,则依次全部加载到内存中。当program2运行时,同样的加载program2.o,然后发现program2.o依赖于lib.o,但是此时lib.o已经存在于内存中,这个时候就不再进行重新加载,而是将内存中已经存在的lib.o映射到program2的虚拟地址空间中,从而进行链接(这个链接过程和静态链接类似)形成可执行程序。

  • 库相关
    1 编写库:
    ①新建空项目
    ②编写相应的.h和.cpp文件实现功能(具体待以后总结)在这里插入图片描述
    ③项目属性中设置在这里插入图片描述
    ④build过后,lib文件就生成了
    2 引用库:
    将要使用库的项目中新建两个文件夹(不建也可以)include和lib
    将上面编写的.h和.cpp复制到inclde中,lib复制到lib中
    在包含目录中添加包含.h和.cpp的文件夹路径在这里插入图片描述
    附加库目录中添加lib的路径,并添加依赖项在这里插入图片描述
    在这里插入图片描述

然后在项目中引用.h即可使用库中函数;要注意的是link若报错,则添加忽略项即可。
2 动态库:
首先项目属性设置为输出dll文件。
编写相应的.h和.cpp文件实现功能。
要注意指定导出的变量或函数,有以下方法:

#ifdef MYDLL_EXPORTS
#define MYDLL_API __declspec(dllexport)
#else
#define MYDLL_API __declspec(dllimport)
#endif 
//以上是将declspec用宏定义包装(别名),dllexport意思是被此宏修饰的变量或函数是要从dll中导出去的
//而dllimport的意思是要从别的dll中读取进来
//此方法不能有.def文件,一定不能有!
 
//导出类
class MYDLL_API Rectangle
{
public:
    double getarea(double w, double h);
    void   print();
 
};
 
//导出函数,变量也一样可以导出
MYDLL_API int mysum(int a, int b);//注意是写在函数前面!
//一般都在.h中写好,但在.cpp中写也一样,注意只能有一处写,不然报错
//导出类若有了修饰,则它的成员函数不需要写这个修饰

还有就是编写.def文件,并加入到设置
在这里插入图片描述
内容如下:

LIBRARY MyDll(dll的名称,是真的dll的名称哦,引用dll时都用这个名称,若不用def则就是生成文件的名字)
EXPORTS
函数名1(如MyAdd)
函数2...

引用动态库:

//只需要Dll文件放在exe文件同一目录下即可
#include<iostream>
#include<Windows.h>
typedef int(*Pmysum)(int a, int b);//定义一个指针函数类型
int main()
{
    HMODULE Hdll = LoadLibrary(L"Add.dll");//获取dll地址
    if (Hdll != NULL)
    {
        Pmysum mysunm = (Pmysum)GetProcAddress(Hdll, "Sub");//获取dll中的函数地址
        if (mysunm != NULL)
        {
            std::cout << "调用两变量相加函数:" << mysunm(7, 2);
        }
    }
    FreeLibrary(Hdll);//卸载dll
    return 0;
}

第二种方法是,将.h、.lib和.dll都放在某一目录中,在项目属性中,包含目录指定.h,附加库目录指定.lib,附加依赖项指定.lib,.dll放在exe同一目录下。

//若只指定包含目录.h,则用以下方法
#pragma comment(lib,"MyDll.lib) (此方法需要将该lib文件放到与exe同目录下)
PaddleOCR C++推理编译:解决YAML-CPP链接错误的完整指南 C++项目开发中,依赖管理是构建过程中的关键环节,尤其涉及第三方的集成。CMake作为主流的跨平台构建工具,通过find_package机制管理的查找链接,其原理在于解析提供的配置文件,自动设置包含路径和链接。这一机制的技术价值在于实现项目依赖的自动化管理,提升构建的可移植性和可重复性。然而,当依赖的CMake配置文件缺失或路径不匹配时,就会出现典型的“未定义引用”链接错误,这在集成复杂如PaddleOCR时尤为常见。应用场景广泛存在于计算机视觉、工业自动化等需要部署深度学习模型的项目中。本 阅读详情

相关推荐

C++编译链接

C++编译链接

enyp80的博客 925

C/C++编译链接过程

cl.exe和link.exe分别是visual studio 中的编译器和链接器 配置属性中的【c/c++】(设置编译的一些选项) 和 【链接器】选项页中,最后的那个命令行汇总了所有生效的设置,就是最终执行的命令行 配置属性中的VC++ 目录用于设置各个路径,相当于设置环境变量PATH(搜可执行文件的路径): INCLUDE(搜include中文件的路径) LIBPATH(搜使用usin...

u012138730的专栏 8870

编译器角度理解C++代码的编译链接

C++代码的编译链接示例代码编译过程编译编译汇编链接过程相关面试题参考资料 由于Windows操作系统下的IDE不好查看编译链接的详细过程,故本文使用Linux操作系统。 具体版本:Linux version 4.15.0-30deepin-generic。 示例代码 示例代码有两个:main.cpp 和 sum.cpp: // main.cpp #include <iostream> using namespace std; extern int gdata; int sum(int,in

YY_Song 's blogs 2019

C/C++程序编译链接(一) 编译链接的概念

编译器本质上是将源代码中的高级语言翻译成低级语言,比如翻译成intel x86平台的汇编代码。上面简单的描述编译器的主要工作后,可以体会到编译器的复杂性,通常一个大型的C/C++项目有成千上万上个源文件,源文件间的调用关系错中复杂,编译器生成正确的汇编代码,要理解这些调用关系产生正确符号地址等,再生成正确的执行文件,还要讲究速度。这样简单的想想都很复杂。平常我们认为C/C++复杂,认为它们是比较低级的语言,但是在它们背后,编译器还是做了大量的工作。那么对python,java这样简洁,高效的语言。

mo4776的博客 2815

C++编译链接简介

内核主要是用来执行指令集的,指令集有很多,早期intel发明的x86指令集,32位地址总线,有哪此寄存器,有哪些汇编指令,如何加载执行可执行文件。后来AMD在x86的基础上扩展支持了64指令,这种新的架构也被称为x86-64,有时也会简称x64或AMD64。x64兼容32位,也即x64有两套指令集。x86,x64是intel和AMD共享专利的指令集,也即这两家的通用CPU指令集是一样的。指令集有很多,还有ARM公司的ARM指令集,还有开源的MIPS指令集。

飞鹤的程序员人生 2567

C++编译链接

链接编译之后会带走所有的.obj目标文件进行链接链接会检查用到或者声明的函数是否存在,有趣的是,如果你定义了一个函数a,里面调用的函数b不存在,但实际上你没有用到函数a,此时也会报链接错误,这是因为编译器觉得你在这个文件用不到,但可能会在其他文件用到函数a,所以还是检查了a函数链接问题,那其实如果我们告诉编译器我只在这个文件用到函数a,其他文件不会用到,那么编译器就不会检查这个文件没有用到的函数链接问题,那么如何实现呢?c++编译生成一个.obj的可执行文件,此时会加载预处理和检查语法错误。

qq_43485816的博客 229

Cpp学习——编译链接

编译链接解释

qq_41934502的博客 723

C++ 编译链接机制的演化路径

以 完全问题驱动的方式 推导 C++ 编译链接机制的演化路径。每一步都基于前一阶段无法解决的问题,提出新的设计方案,不依赖当前 GCC 或 MSVC 的实现细节,而是像一个架构师一样,从零开始设计一个现代 C++ 系统。

he_wen_jie的博客 750

C++多个文件编译链接方法

问题描述: 写了mytime.h,mytime.cpp,usetime.cpp三个文件,其中usetime.cpp引用了mytime.h,这时用指令 g++ mytime.h -o mytime.o 就会报错collect2: error ld returned 1 exit status。 解决方案: g++ -c -o mytime.o mytime.cpp g++ -c -o usetime.o usetime.cpp g++ -o test mytime.o usetime.o 这样下来就避免了上

舒兆国的博客 1754

CPP编译链接过程

define。

weixin_44236630的博客 1246

编译linux .o成cpp_从四个问题透析Linux下C++编译&链接

摘要:编译&链接对C&C++程序员既熟悉又陌生,熟悉在于每份代码都要经历编译&链接过程,陌生在于大部分人并不会刻意关注编译&链接的原理。本文通过开发过程中碰到的四个典型问题来探索64位linux下C++编译&链接的那些事。注1:本文所涉及工具可从http://www.gnu.org/software/binutils/获取详细信息注2:本文示例代码图片中,每...

weixin_30577815的博客 2052

c++编译链接过程

c++源码处理转化为可执行文件的流程可以分为三个部分:预处理(preprocessing),编译(compilation)链接(linking)。 1. Preprocessing 该过程是由预处理器对源码中的预处理指令进行处理,例如预处理器将#include进cpp源码的头文件复制到源码中,并使用具体数值替换由#define所定义的符号常量。 2. Compilation 编译器对预处理后的纯源码(即此时的源码不包含任何预处理指令)进行编译,将其转换为汇编代码(xxx.s). 汇编器对汇编代码处理后生

bonjour001的博客 1134

记录C++编译的两个坑点(链接错误):模板不支持分离编译main.cpp不能调用另一个cpp文件

结论如下: 1)使用模板的cpp文件实现不能分离编译,也就是模板的声明和实现都要在同一个.h文件中,然后.cpp 文件调用就好了。如果非要分离编译,就会导致链接错误了。 2)main.cpp不允许直接去调用另一个.cpp文件,这样也会导致链接错误。 因为A.cpp(include "B.cpp" )在预处理阶段会将B.cpp的代码引用进去,并且编译器也会单独预处理B.cpp,然后A.cppB....

algsup 937

C++编译链接

C++分离式编译编译链接过程

西电卢本伟的博客 1715

.cpp.h文件的关系详解(预处理、编译、汇编、链接

C++程序通常分为头文件(.h)和源文件(.cpp):头文件存放函数声明、类定义等接口,源文件存放具体实现。编译过程包括预处理、编译、汇编和链接四个步骤,其中链接器负责将各目标文件中的符号引用定义进行匹配。关键点在于:1)头文件仅提供声明,源文件提供实现;2)编译器检查语法但不关心实现位置;3)链接阶段通过符号表匹配引用和定义;4)遵循单一定义规则,避免同名冲突。这种分离方式提高了代码的模块化和可维护性,同时通过分步编译提升了效率。

weixin_44115575的博客 1万+

C++手动编译链接

有三个文件A.cpp,A.h, main.cpp main.cpp和A.cpp中include了A.h。 编译过程: g++ -o A.o -c A.cpp g++ -o main.o -c main.cpp g++ -o main.out A.o main.o ./main.out

Woody0729的博客 898

C 怎么读取Cpp文件_C/C++编程笔记:C/C++编译链接

C/C++文件C/C++程序文件包括 .h .c .hpp .cpp,其中源文件(.c .cpp)是基本的编译单元,头文件(.h .hpp)不会被编译编译。C/C++项目构建(build)过程,分为以下几个步骤 预处理 → 编译链接。预编译编译过程可以理解为编译器(实际上是预处理器,这里统称为编译器就可以了)在正式编译之前处理C/C++文件中的预处理命令,即#开头的代码。常用的几个预处...

weixin_39728572的博客 1029

C++编译链接

了解C++编译链接过程

冯同学的博客 1664
上一篇: 修改Visual Studio默认分配的堆栈内存
下一篇: ifdef的使用
Kiryee
博客等级 码龄7年 1粉丝 46原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值