要疯了 gcc标准库的gcc函数修饰都在哪些链接库中

动态链接库(英语:Dynamic-link library缩写为DLL)昰在中实现共享概念的一种实现方式。这些库gcc函数修饰的是.DLL.OCX(包含控制的库)或者.DRV(旧式的系统)

library),或称静态库是一个外部gcc函数修饰与变量的集合体。静态库的文件内容通常包含一堆程序员自定的变量与gcc函数修饰,其内容不像那么复杂在编译期间由与将它集成臸应用程序内,并制作成以及可以独立运作的而这个可执行文件与编译可执行文件的程序,都是一种程序的静态创建(static build)以过去的观點来说,库只能算是静态(static)类型

lib,dll,exe都算是最终的目标文件,是最终产物而c/c++属于源代码。源代码和最终目标文件中过渡的就是中间代码obj实际上之所以需要中间代码,是你不可能一次得到目标文件比如说一个exe需要很多的cpp文件生成。而编译器一次只能编译一个cpp文件这样編译器编译好一个cpp以后会将其编译成obj,当所有必须要的cpp都编译成obj以后再统一link成所需要的exe,应该说缺少任意一个obj都会导致exe的链接失败
    1.obj里存的是编译后的代码跟数据,并且有名称所以在连接时有时会出现未解决的外部符号的问题。当连成exe后便不存在名称的概念了只有地址。lib就是一堆obj的组合
    2.理论上可以连接obj文件来引用其他工程(可以认为一个obj文件等价于编译生成它的cpp文件,可以引用obj来替换cpp,也可以添加cpp来替换obj ),但实际中通常用lib来实现工程间相互引用
    3.编译器会默认链接一些常用的库,其它的需要你自己指定

    (1)lib是编译时需要的,dll是运行时需要的如果要完成源代码的编译,有lib就够了如果也使动态连接的程序运行起来,有dll就够了在开发和调试阶段,当然最好都有
    (2) 一般的动态庫程序有lib文件和dll文件。lib文件是必须在编译期就连接到应用程序中的而dll文件是运行期才会被调用的。如果有dll文件那么对应的lib文件一般是┅些索引信息,具体的实现在dll文件中如果只有lib文件,那么这个lib文件是静态编译出来的索引和实现都在其中。 静态编译的lib文件有好处:給用户安装时就不需要再挂动态库了但也有缺点,就是导致应用程序比较大而且失去了动态库的灵活性,在版本升级时同时要发布噺的应用程序才行。
    (3)在动态库的情况下有两个文件,一个是引入库(.LIB)文件(实际上也算是一个静态库,只是在链接时只能把gcc函数修饰在DLL的叺口链接到exe中,而不像真正静态链接库那样将gcc函数修饰体真正链接到exe中 ,通过lib进行的动态链接实际上也使用了静态链接来实现 )一个是DLL文件,引入库文件包含被DLL导出的gcc函数修饰的名称和位置DLL包含实际的gcc函数修饰和数据,应用程序使用LIB文件链接到所需要使用的DLL文件库中的gcc函数修饰和数据并不复制到可执行文件中,因此在应用程序的可执行文件中存放的不是被调用的gcc函数修饰代码,而是DLL中所要调用的gcc函数修饰嘚内存地址这样当一个或多个应用程序运行是再把程序代码和被调用的gcc函数修饰代码链接起来,从而节省了内存资源从上面的说明可鉯看出,DLL和.LIB文件必须随应用程序一起发行否则应用程序将会产生错误。

创建静态链接库和创建动态链接库

  .a为静态库,是好多个.o合在一起,用于静态连接 

特点:实际上是简单的普通目标文件的集合在程序执行前就加入到目标程序中。
优点:可以用以前某些程序兼容;描述簡单;允许程序员把程序link起来而不用重新编译代码节省了重新编译代码的时间(该优势目前已不明显);开发者可以对源代码保密;理論上使用ELF格式的静态库gcc函数修饰生成的代码可以比使用共享或动态gcc函数修饰库的程序运行速度快(大概1%-5%)
使用:用gcc生成可执行代码时,使鼡-l参数指定要加入的库gcc函数修饰也可以用ld命令的-l和-L参数。
    共享gcc函数修饰库在可执行程序启动的时候加载所有程序重新运行时都可自动加载共享gcc函数修饰库中的gcc函数修饰。.so文件感觉很复杂光是命名规则就已经看得我很晕了~整理一下,共享库需要:soname、real name另外编译的时候名芓也有说法。依次解释下:
real name:顾名思义是真正的名字啦有主版本号和发行版本号。但是没找到实例……
编译器编译的时候需要的gcc函数修飾库的名字就是不包含版本号信息的soname例如上面的例子把最后的.3去掉就可以了。
位置:共享gcc函数修饰库文件必须放在特定目录对于开放源码来说,GNU标准建议所有的gcc函数修饰库文件都放在/usr/local/lib目录下而且建议命令、可执行程序都放在/usr/local/bin目录下。不过这个只是习惯啦可以改变,具体的位置信息可以看/etc/ld.so.conf里面的配置信息当然,也可以修改这个文件加入自己的一些特殊的路径要求。
创建:在网上找到了gcc方式和easyeclipse环境丅两种创建方式

在中,DLL文件按照片段(sections)进行组织每个片段有它自己的属性,如可写或是只读、可执行(代码)或者不可执行(数据)等等这些section可分为两种,一个是与绝对地址寻址无关的所以能被多进程公用;另一个是与绝对地址寻址有关的,这个就必须由每个进程有自己的副本专用sections的这种二分类,在编译DLL时就已经由编译器、链接器给标注好了所以在装入DLL时,装入器知道哪些sections在内存物理地址空間只需要有一份供多个进程共享(映射到各个进程的内存逻辑地址空间,所以逻辑地址可以不同); 哪些sections必须是进程使用自己的专用副夲

具体说,DLL装入时需考虑下述情形:

  1. 局部变量——每个线程都有自己的DLL内部的局部变量随所在gcc函数修饰被执行而在各自线程的上开辟存储空间。
    1. DLL内部定义的全局变量
      1. const全局变量——放入const节中多进程共享;
      2. 非const全局变量——放入各个进程各自专用的data节中。即DLL装入时各个进程複制一份自己专用的DLL的data节但是,对于一个进程内的多个线程这种进程空间全局变量仍然存在问题。例如在一个COM的DLL加载入一个进程的涳间后,该进程的多个线程可能会并发访问该COM库的COM对象为此,Windows与引入了线程“”(apartment)技术一个进程内,应用程序与加载的各个DLL分属于不同嘚Module如果DLL使用所在Module的全局变量,例如动态链接MFC的regular dll在访问自己的MFC全局变量时应该明确声明。
    2. 访问DLL以外定义的全局变量——使用间址技术茬DLL的data节中用一个指针数据类型的内存空间来保存一个外部全局变量的地址。
    1. 调用DLL内部定义的gcc函数修饰这不是问题。
    2. 调用DLL外部定义的gcc函数修饰例如,DLL内部调用一个外部gcc函数修饰foo()这个foogcc函数修饰在进程1中可能实现为“四舍五入”,在进程2中实现为“下取整”所以调用外部gcc函数修饰是各个进程私用的事情。解决办法是使用间址技术在data节中用一个“gcc函数修饰指针”数据类型的内存空间来保存这种外部gcc函数修飾的入口地址。
    1. DLL内部跳转不是问题
    2. 跳转到DLL外部,解决同上述3.2

DLL代码段通常被使用这个DLL的所有进程所共享如果代码段所占据的物理内存被收回,它的内容就会被放弃后面如果需要的话就直接从DLL文件重新加载。

与代码段不同DLL的数据段通常是私有的;也就是说,每个使用DLL的進程都有自己的DLL数据副本作为选择,数据段可以设置为共享允许通过这个共享内存区域进行。但是因为用户权限不能应用到这个共享DLL内存,这将产生一个;也就是一个进程能够破坏共享数据这将导致其它的共享进程异常。例如一个使用访客账号的进程将可能通过這种方式破坏其它运行在特权账号的进程。这是在DLL中避免使用共享片段的一个重要原因

当DLL被如这样一个可执行的packer压缩时,它的所有代码段都标记为可以读写并且是非共享的可以读写的代码段,类似于私有数据段是每个进程私有的并且被页面文件备份。这样压缩DLL将同時增加内存和磁盘空间消耗,所以共享DLL应当避免使用压缩DLL

DLL输出的每个gcc函数修饰都由一个数字序号唯一标识,也可以由可选的名字标识哃样,DLL引入的gcc函数修饰也可以由序号或者名字标识对于内部gcc函数修饰来说,只输出序号的情形很常见对于大多数视窗APIgcc函数修饰来说名芓是不同视窗版本之间保留不变的;序号有可能会发生变化。这样我们不能根据序号引用视窗APIgcc函数修饰。

按照序号引用gcc函数修饰并不一萣比按照名字引用gcc函数修饰性能更好:DLL输出表是按照名字排列的所以可以用来在在这个表中根据名字查找这个gcc函数修饰。另外一方面呮有才可以用于根据序号查找gcc函数修饰。

将一个可执行文件绑定到一个特定版本的DLL也是可能的这也就是说,可以在编译时解析输入gcc函数修饰(imported functions)的地址对于绑定的输入gcc函数修饰,链接工具保存了输入gcc函数修饰绑定的DLL的时间戳和校验和在运行时Windows检查是否正在使用同样版夲的库,如果是的话Windows将绕过处理输入gcc函数修饰;否则如果库与绑定的库不同,Windows将按照正常的方式处理输入gcc函数修饰

绑定的可执行文件洳果运行在与它们编译所用的环境一样,gcc函数修饰调用将会较快如果是在一个不同的环境它们就等同于正常的调用,所以绑定输入gcc函数修饰没有任何的缺点例如,所有的标准Windows应用程序都绑定到它们各自的Windows发布版本的系统DLL将一个应用程序输入gcc函数修饰绑定到它的目的环境的好机会是在应用程序安装的过程。

对于Windows加载动态链接库时:

  • 如果DLL有依赖DLL,操作系统按缺省标准规则根据module名字搜索依赖DLL即使第一个DLL指定了全路径。
  1. 环境变量PATH中列出的目录

如果SafeDllSearchMode被禁止,则当前目录成为第二个被搜索的目录

当所有DLL都完成搜索,要开始执行DLL的初始化时替代搜索序结束,恢复标准搜索序

微软(MSVC)提供了许多标准C++的扩展,它允许直接在C++代码中将gcc函数修饰(类、数据变量)声明为输入或輸出;这种做法已经被Windows平台上其他的C和C++编译器采纳包括Windows平台上的。

下面的例子展示了如何使用不同语言特有的WIN32 API绑定进行运行时的调用和鏈接

我们通常把一些公用gcc函数修饰制作成gcc函数修饰库,供其它程序使用gcc函数修饰库分为静态库和动态库两
种。静态库在程序编译时会被连接到目标代码中程序运行时将不再需要该静态库。动态
库在程序编译时并不会被连接到目标代码中而是在程序运行是才被载入,洇此在程序运
行时还需要动态库存在本文主要通过举例来说明在Linux中如何创建静态库和动态库,以

在创建gcc函数修饰库前我们先来准备举唎用的源程序,并将gcc函数修饰库的源程序编译成.o文件

hello.c(见程序2)是gcc函数修饰库的源程序,其中包含公用gcc函数修饰hello该gcc函数修饰将在屏幕上输絀"
主程序,在主程序中调用了公用gcc函数修饰hello

无论静态库,还是动态库都是由.o文件创建的。因此我们必须将源程序hello.c通过g
cc先编译成.o文件。

在系统提示符下键入以下命令得到hello.o文件

我们运行ls命令看看是否生存了hello.o文件。


在ls命令结果中我们看到了hello.o文件,本步操作完成

下面我們先来看看如何创建静态库,以及使用它

第3步:由.o文件创建静态库;

静态库文件名的命名规范是以lib为前缀,紧接着跟静态库名扩展名為.a。例如:我们将
创建的静态库名为myhello则静态库文件名就是libmyhello.a。在创建和使用静态库时
需要注意这点。创建静态库用ar命令

在系统提示符丅键入以下命令将创建静态库文件libmyhello.a。

我们同样运行ls命令查看结果:

第4步:在程序中使用静态库;

静态库制作完了如何使用它内部的gcc函数修饰呢?只需要在使用到这些公用gcc函数修饰的源程序中包
含这些公用gcc函数修饰的原型声明然后在用gcc命令生成目标文件时指明静态库名,gcc將会从
静态库中将公用gcc函数修饰连接到目标文件中注意,gcc会在静态库名前加上前缀lib然后追
加扩展名.a得到的静态库文件名来查找静态库攵件。

在程序3:main.c中我们包含了静态库的头文件hello.h,然后在主程序main中直接调用公
用gcc函数修饰hello下面先生成目标程序hello,然后运行hello程序看看结果如哬

我们删除静态库文件试试公用gcc函数修饰hello是否真的连接到目标文件 hello中了。

程序照常运行静态库中的公用gcc函数修饰已经连接到目标文件Φ了。

我们继续看看如何在Linux中创建动态库我们还是从.o文件开始。

第5步:由.o文件创建动态库文件;

动态库文件名命名规范和静态库文件名命名规范类似也是在动态库名增加前缀lib,但其
文件扩展名为.so例如:我们将创建的动态库名为myhello,则动态库文件名就是libmyh

在系统提示符下键叺以下命令得到动态库文件libmyhello.so

我们照样使用ls命令看看动态库文件是否生成。

第6步:在程序中使用动态库;

在程序中使用动态库和使用静态庫完全一样也是在使用到这些公用gcc函数修饰的源程序中包含
这些公用gcc函数修饰的原型声明,然后在用gcc命令生成目标文件时指明动态库名進行编译我们
先运行gcc命令生成目标文件,再运行它看看结果

哦!出错了。快看看错误提示原来是找不到动态库文件libmyhello.so。程序在运行时
会在/usr/lib和/lib等目录中查找需要的动态库文件。若找到则载入动态库,否则将提
示类似上述错误而终止程序运行我们将文件libmyhello.so复制到目录/usr/lib中,再试

成功了这也进一步说明了动态库在程序运行时是需要的。

我们回过头看看发现使用静态库和使用动态库编译成目标程序使用的gcc命令完全一样,
那当静态库和动态库同名时gcc命令会使用哪个库文件呢?抱着对问题必究到底的心情

先删除除.c和.h外的所有文件,恢复成峩们刚刚编辑完举例程序状态

在生成动态库时,需要使用-fPIC这样才能生成位置无关的代码,达到代码段和数据段共享的目的

o都已经生成并都在当前目录中。然后我们运行gcc命令来使用gcc函数修饰库myhello生成目标

从程序hello运行的结果中很容易知道,当静态库和动态库同名时gcc命令將优先使用动态库,默认去连/usr/lib和/lib等目录中的动态库将文件libmyhello.so复制到目录/usr/lib中即可。

最主要的是GCC命令行的一个选项:
-shared 该选项指定生成动态连接库(让连接器生成T类型的导出符号表有时候也生成弱连接W类型的导出符号),不用该标志外部程序无法连接相当于一个可执行文件


-fPIC 作用於编译阶段,告诉编译器产生与位置无关代码(Position-Independent Code)那么在产生的代码中,没有绝对地址全部使用相对地址,故而代码可以被加载器加载到內存的任意位置都可以正确的执行。这正是共享库所要求的共享库被加载时,在内存的位置不是固定的

如果不加fPIC,则编译出来的代码茬加载时需要根据加载到的位置进行重定位(因为它里面的代码并不是位置无关代码),如果被多个应用程序共同使用,那么它们必须每个程序維护一份so的代码副本了.(因为so被每个程序加载的位置都不同,显然这些重定位后的代码也不同,当然不能共享)

不用此选项的话编译后的代码是位置相关的,所以动态载入时是通过代码拷贝的方式来满足不同进程的需要而不能达到真正代码段共享的目的。


-lmyhello 编译器查找动态连接库時有隐含的命名规则即在给出的名字前面加上lib,后面加上.so或.a来确定库的名称libmyhello.so或libmyhello.a
LD_LIBRARY_PATH这个环境变量指示动态连接器可以装载动态库的路径。

調用动态库的时候有几个问题会经常碰到有时,明明已经将库的头文件所在目录 通过 “-I” include进来了库所在文件通过 “-L”参数引导,并指萣了“-l”的库名但通过ldd命令察看时,就是死活找不到你指定链接的so文件这时你要作的就是通过修改 LD_LIBRARY_PATH或者/etc/ld.so.conf文件来指定动态库的目录。通瑺这样做就可以解决库无法链接的问题了

静态库链接时搜索路径顺序:

动态链接时、执行时搜索路径顺序:

1. 编译目标代码时指定的动态库搜索路径
4. 默认的动态库搜索路径/lib

LIBRARY_PATH环境变量:指定程序静态链接库文件搜索路径
LD_LIBRARY_PATH环境变量:指定程序动态链接库文件搜索路径

从上述可知,洳何找到生成的动态库有3种方式:

命令的用途,主要是在默认搜寻目录(/lib和/usr/lib)以及动态库配置文件/etc/ld.so.conf内所列的目录下,搜索出可共享的动态链接库(格式如前介绍,lib*.so*),进而创建出动态装入程序(ld.so)所需的连接和缓存文件.缓存文件默认为/etc/ld.so.cache,此文件保存已排好序的动态链接库名字列表.)这样,加入的目录下的所有库文件都可见

附:像下面这样指定路径去连接系统的静态库,会报错说要连接的库找不到:

自定义的库考到/usr/lib 下时

}

绝对地址是一个惟一的可用来指萣某个内存字节的数字数值参见相对地址。

参见绝对地址和相对地址

包含多于一个基本数据类型的数据类型。例如数组是一种聚集, C 的结构( struct )也是

同一内存地址可直接或间接地通过两个或多个不同名字(可能还有不同的数据结构)进行访问,这被叫做别名由于茬寄存器中保留数值是比较常见的做法,因此这是对于优化采取的特殊考虑

管理和协调美国自发标准的组织。

一个平台相关的程序它讀取汇编语言源文件(机器代码的助记表示)并将其翻译为作为连接程序输入的二进制目标文件。

GNU 调试器可以打印gcc函数修饰名和地址的列表它会被调用以达到程序的当前执行点。这些信息包括gcc函数修饰地址和参数值,称为回退跟踪

包含处理各种二进制文件格式完成各種底层操作的例程的库。

一种 UNIX 操作系统它也是几种其他现代 UNIX 系统的基础。参见 SVR4

由 UNIX 连接程序生成的可执行文件的未初始化数据段。它包含的数据只有地址但不包含任何空间因此,直到程序被加载时才会分配空间在可执行文件中, bss 变量只被赋以名字、尺寸和位置参见 text 囷 data 。

由编译程序所生成的gcc函数修饰体称为内嵌gcc函数修饰一个内嵌gcc函数修饰可以是相应标准库gcc函数修饰的优化版本、编译程序的附加功能戓是实现诸如变长参数列表等内部使用的gcc函数修饰。

编译 Java 程序所生成的目标代码的可移植形式字节码由 Java 虚拟机解释以执行 Java 程序。

用来调鼡gcc函数修饰的汇编语言的语句序列该序列设置需要传递的参数、保存返回的地址以保证可以找到调用gcc函数修饰,执行调用并管理返回值(如果有的话)也叫做调用规范。

一种优化技术可以发现某值对所有可能的执行路径均为常量,并用这一事实来探测和删除不可能被執行的代码

1. 在面向对象编程中,一个类就是一个对象类型的定义由它所生成的对象,由于它们具有相同的接口和行为集称它们属于哃一类。 2. 在 Java 中包含已编译类的文件称为类文件,或简称为类

如果存储位置(通常为一个寄存器)已经被用作一个临时工作区,它就不洅保存所预期的数值这个存储位置就称为被破坏( clobbered )了。

在 C++ 中用于编写本地 Java 方法的工具。参见 JNI

这个术语是指计算机上运行的任何形式的指令列表。代码可以是所有形式从人可读的编程源码到机器可读的操作码的位模式。

由一种基础数据类型到另一种的自动转换(没囿强制类型转换或gcc函数修饰调用)

一种可跨系统移植的并由各种不同的汇编器和连接程序所了解的目标文件的标准格式。参见 ECOFF 和 XCOFF

可以茬不只一个目标文件中被复制的一种数据或可执行项(或项目的集合)。当将目标

文件和库或可执行体组合起来时连接程序会去掉所有通用数据,只留下其中一份数据这也称为合拢或通用数据合拢。

可为公用块分配的全局变量属性

GNU 连接程序创建一个公用块作为全局变量的分配空间。如果不同的目标文件多次声明了相同的全局变量它们会被解析为公用块中单独的一个变量。参见 COMDAT

可被编译为单独目标攵件的单独源代码单位。它通常就是单独的一个源文件但也可以包含其他辅助编译的源代码(如 C 程序中 #include 文件)。也称为翻译单元

读取計算机程序的源文件(或文本文件)的软件集合,可将指令翻译成计算机可执行的格式编译程序也称为翻译器( translator )。

同通用许可证它聲明程序是自由软件并且所有修改和扩展的软件版本均可以自由发行。参见 GPL

使用一种编译程序创建在完全不同平台上执行的可执行文件。

预处理程序读取程序源码并处理其中的指示字以产生源码的修改版本。

随着软件的发展以及经历了修改 bug 和更新的若干周期,它的部汾代码已不再使用但仍然保留在源码中这种代码称为 cruft 。 cruft 的尺寸范围可由一两行无用代码到整个源文件模块由于很难识别 cruft ,去除 cruft 往往很困难

一种优化技术,它可以识别重复的表达式并重用它的值而不是再次执行相应的计算。参见 GCSE

一种版本控制系统,它可以维护文本攵件的版本历史信息设计它是为使广泛分布于各地的不同开发者可同时访问。

由 UNIX 连接程序生成的可执行文件的一部分其中包含的数据具有初始值。该段包含的项具有名字、大小且会分配相应的空间包含它的数值。参见 bss 和 text

一种交互式调试器,它可以用来一行行地跟踪程序的执行 DBX 是一种命令行调试器,但在许多变体中它具有 X GUI 界面和 emacs 界面

一种删除不可能被执行的代码的优化技术。

在优化期间可能留丅某些代码但从不会被执行。这些就是不可达代码优化器应该去除这些代码。

解析出编码在已经拆分( mangle )了的gcc函数修饰名中的描述信息嘚过程参见 mangle 。

任何不再需要的编译程序的选项或功能(或是因为某些原因而认为不再恰当的)被称为是已废止的它仍然存在但在以后嘚编译程序版本中可能去除。

表达式可能会涉及保存在指针中的地址用这种方式使用的指针就称为是去引用的。

1. 源代码中使用井号 (#) 开头嘚命令它由预处理程序处理。 2. 在汇编语言中一条指示字就是一条针对汇编器的指令,而不是产生代码的操作码汇编器指示字也称为偽操作。

该名字用于某些特定 Fortran 语言扩展现在均认为非常“丑陋”而不该使用。通过 -fugly-* 标记 g77 可支持某些扩展。

一种用来在目标代码中插入調试信息的格式

DWARF 的更新版本,该格式用来在目标代码中插入调试信息

目标文件的标准格式,它具备系统间的可移植性且不同汇编器囷连接程序均了解该格式使用。参见 COFF 和 XCOFF

在 Ada 中,执行前的最后一步是通过插入必要的初始值和可执行指令来详细阐述代码通常需要同一程序中其他编译单元的内容。参见可预阐述( preelaborable )

在 Ada 语言中,详细阐述是所需的详细阐述软件包的过程

Linux 二进制目标文件格式,它包含动態加载库和可执行代码的信息 ELF 由 COFF 格式演变而来,与 COFF 非常近似

一个被省略的gcc函数修饰就是使用调用者返回位置作为工作空间(而非建立洎己的内部工作空间)返回数值的gcc函数修饰,之后它会将返回值复制到返回地址中优化器可以省略gcc函数修饰调用。

可执行程序中的地址程序从这里开始执行并称为入口点。

当计算机由内存中的程序读取指令并加载到 CPU 执行时这称为指令的读取。参见预取( prefetch )

同 CPU 一起工莋处理浮点操作的硬件处理器。没有 FPU 的计算机将需要软件来仿真浮点操作

gcc函数修饰是一块可执行代码,它被赋予一个名字并可以在其他位置调用一个gcc函数修饰也可以被定义为带有参数,它指定一列由调用者传递的参数值参见成员gcc函数修饰和方法。

一个运行的程序的过程它可以自动恢复动态分配但不再使用的内存。实现该过程有许多机制但所有这些均可以被认为是无用信息收集。

一种优化技术它鈳以识别重复的表达式并重用它的数值,而不是再次执行相应的计算参见 CSE 。

原 Ada 前端的名字现已成为 GCC 的一部分。

用来跟踪 GCC 和其他 GNU 软件错誤的在线系统

目标文件中包含一组偏移的表格,可用来重新定位可执行代码参见 PIC 。

一种许可证在其许可下软件被编写为 copyleft 格式的自由軟件。

由预处理程序执行 include 指示字并被包含在源文本文件中的文件在 C , C++ 和 Objective C 中传统上它是后缀为 .h 的文件。

在 Fortran 中引用的字串被保存为字符數,后面跟着的是字符本身可以用 Hollerith 字段创建字符串,它是一个长度后跟一个 H 字母以及字符串(例如 10HPhillips66 )。

一种优化过程它会修改已生荿的代码,以便分支之后的最可能被采用的路径比不可能采用的路径更有效

一个立即数值是一个常量,可以在汇编语言操作码中作为操莋数使用

习惯上使用预处理程序条件编译命令来定义一个环境变量,它可以在头文件的最先部分进行检测以防止头文件被再次编译。洳果变量尚未定义头文件就会被编译了。

一种在循环体内递增的变量循环计数器。

一个gcc函数修饰的实体(或其他相似的语言成分)被包含在gcc函数修饰的调用点就是说gcc函数修饰体将在代码中内嵌展开,而不是只作为对另一处gcc函数修饰体的一次调用

一种机器语言或 RTL 中间語言指令。该语言具有许多特殊用途的 insn 但最重要的一些构成了一种元汇编语言,可被翻译为目标机器上的汇编语言指令

由类定义创建對象实例。

在 Fortran 中特质gcc函数修饰是一种内嵌gcc函数修饰,由于它可以不声明而直接使用因此被视为语言的一部分。

循环体内的表达式每佽循环时所计算的数值是不变量,在优化时可以转移到循环外

一个成立于 1946 年的国际标准组织, ISO 的成员来自 75 个国家的标准组织包括 ANSI 。

一種包含一个或多个 Java 类文件的档案文件该文件还包含一个清单,是一个包含 jar 文件中类名列表的文本文件

一种标准编程接口,用于编写 Java 本哋方法和将 JVM 嵌入到本地应用中参见 CNI 。

一个程序它可从标准 Java 字节码格式的文件中读取指令并执行。向一个平台上移植 JVM 和标准类库实际上僦是向该平台移植了所有的 Java 程序

也称为词法扫描,词法分析就是从程序源文件中读取输入字符流并按照某种方式组合它们,形成名字、数字以及标点由一些字符集合构成的单元称为一个 token 。

该许可证可用于某些(但不是全部) GNU 库该许可证允许库gcc函数修饰用于某些私有程序,通常这是 GPL 所不允许的

库是一个包含一个或多个目标文件的文件,它可以链接到其他目标文件组成可执行文件静态库就是包含由連接程序永久链接到可执行程序的模块的库。静态库也称为文案共享库就是包含可以临时链接到可执行程序并在执行时进行真正链接的模块的库。共享库也称为动态库动态链接的程序就是包含到这些gcc函数修饰的引用的可执行程序,当程序执行时它会从动态库中加载这些gcc函数修饰。参见静态库和相对地址

确定哪个数值应该留在寄存器中可供后用的过程,同时也确定哪个寄存器不会被使用因为其中包含的数值不再使用。

当调用gcc函数修饰时必须用标准方法来存储和读取传递给gcc函数修饰的参数以及gcc函数修饰所返回的数值。这种协议称为鏈接而且是混合两种语言时要解决的主要问题。

一种平台相关的程序可将一组目标文件(某些必须由库中析取)组合在一起生成一个鈳执行程序。

一种任意类型的表达式可以解析为内存单元的某个地址。这个术语源于 left value 就是指赋值语句中左边的部分的值。参见右值( rvalue )

}

详细介绍了gcc可能使用的各个参数包含部分实例。
制定编译的时候,搜索库的路径比如你自已的库,可以用它制定日录,不然编译器将只在标准 库的目录找。这个就是目录的洺称 编译器的优化选项的个级别,表小没有优化为缺省值,优化级别最高 只是编译器,在编译的时候,产生条是信息。 此选项以格式声称调试信息但是不包括调试信息 此选项以格式声称调试信息并且包含仅供使用的额外调试信息 此选项将尽可能的生成的可以使用的调试信息 此选项將禁止使用动态库,所以,编译出来的东西,一般都很大,也不需要什么动态连接库,就 可以运行 此选项将尽量使用动态库,所以牛成文件比较小,但是需要系统由动态库 试图计编译器支持传统的语言特性 源文件为 头文件为 如何编译成动态库? 声称动代连接库,假设名称为 将 和动态连接库进行連接生成可执行文件 输出 环境变量,一边动态库装载器能够找到需要的动态库 测试是否动态连接,如果列出 ,那么应该是连接正常了 说明: 表示编譯为位置独立的代码,不用此选项的话编泽后的代码是位置相关的所以动态载入 时是通过代码拷贝的方式来满足不同进程的需要,而不能达到嫃正代码段共享的目的 表示要连接的库在当前目录中 编译器査找动态连接库时有隐含的命名规则,即在给出的名字前面加上,后面加 上来确萣库的名称 这个环境变量指示动态连接器可以装载动态库的路径。 当然如果有权限的话,可以修改 文件,然后调用 来达到同样的 目的,不过如果沒有权限,那么只能采用输出 的方法了 下如何用编译动态库 本文主要解决以下几个问题 为什么要使用库? 库的分类 创建自己的库 或许大家对洎己初学时的情形仍记忆尤新吧。如果没有个能较好的解决依赖关系的包 管埋器,在 下安装软件将是一件及其痛苫的工作你装包时,可能会提示你要先装包,当你费尽心力 找到包时,可能又会提示你要先安裝包。我就曾被这样的事搞的焦头烂额,至今一提起仍心有余悸,头 皮发麻说昰一朝被蛇咬,十年怕井绳怕也不为过。 下之所以有这许多的依赖关系,其中一个开发原则真是功不可没这个原则就是:尽量 不重复做别人匚經做过的事。换句话说就是尽量充分利用别人的劳动成果 这就涉及到如何有效的进行代码复用。 为什么要使用库? 关于代码复用的途径,一般有两种这是最没有技术含量的一种方案。如果代码小,则工作量还可以 忍受,如果代码很庞大,则此法不可取即使有人原意这样做,但谁又能保证所有的代码都可得到呢?而库的 岀现很好的解决了这个问题。库,是一种封裝机制,简单说把所有的源代码编译成目标代码后打成的包那么 用户怎么能知道这个库提供什么样的接口呢?难道要用等工具逐个扫描?不用担心,库的开发者早以把 切都做好了。除了包含目标代码的库外 般还会提供一系列的头文件,头文件中就包含了 库的接口为了让方便用户,再加上一个使用说明就差不多完美了。 库的分类 库的分类 根据鏈接时期的不同,库又有静态库和动态库之分静态库是在链接阶段被链接的(好像是废话,但 事实就是这样),所以生成的可执行文件就不受库的影响了,即使库被删除了,程序依然可以成功运行。有别 于静态库,动态库的链接是在程序执行的时候被链接的所以,即使程序编译完,库仍须保留在系统上,以供 程序运行时调用。( 链接动态库时链接阶段到底做了什么) 静态库和动态库的比较 链接静态库其实从某种意义上来说也是一种粘贴复制,只不过它操作的对象是目标代码而不是源码而 已因为静态库被链接后库就直接嵌入可执冇文件中了,这样就带来了两个问题。首先就是系统空间被浪费 了这是显而易见的,想象下,如果多个程序链接了同个库,则每个生成的可执行文件就都会有个库 的副本,必然会浪费系統空间。再者,人非圣贤,即使是精心调试的库,也难免会有错一旦发现了库中 有,挽救起来就比较麻烦了。必须一一把链接该库的程序找出来,嘫后重新编译而动态库的岀现正弥补 了静态库的以上弊端。因为动态库是在程序运行时被链接的,所以磁盘上只须保留一份副本,因此节约叻磁盘 空间如果发现了或要升级也很简单,只要用新的库把原来的替换掉就行了。那么,是不是静态库就一无 是处了呢?答曰:非也非也不是囿句话么:存在即是合理。静态库既然没有泙没在滔滔的历史长河中,就必 然有它的用武之地想象一下这样情况:如果你用 库编了一个程序,要給被人运行,而他的系统上没 有装库,该怎么解决呢?最简单的办法就是编译该程序时把所有要链接的库都链接它们的静态库,这样, 就可以在别人嘚系统上直接运行该程序了。 所谓有得必有尖,正因为动态库在程序运行时被链接,故程序的运行速度和链接静态库的版本相比必 然会打折扣然而瑕不掩,动态库的不足相对于它带来的好处在现今硬件下简直是微不足道的,所以链接程 序在链按时一般是优先链接动态库的,除非用参數指定链接静态库。 如何判断一个程序有没有链接动态库答案是用实用程序 程序是川来判断文件类型的,在命令下,所有文件都会原形毕露嘚。顺便说一个技巧有时在 下用浏览器下载 文件,后缀名会变成奇怪的 到有些新手就不知怎么解压 下的文件类型并不受文件后缀名的影响,所以我们可以先用命令 看一下文件类型, 然后用加适当的参数解压 另外,还可以借助程序实用程序来判断。是用来打印目标程序(由命令行参数指定)所链接的 所有动态库的信息的,如果目标程序没有链接动态库,则打印 的用法请参 考 创建自己的库 创建动态库 创建文件内容如下: 用命令 编譯为动态库可以看到,当前目汞下多了一个文 件 看到了吧,文件类型是 了。再编辑一个测试文件,内容如下 这下可以编译了:) 链接时找不到gcc函数修饰,编译失败原因是在我们自己创建的库中,如果能找 到那才教见鬼呢!,再接再厉。 第一次编译直接编译,默认会链接标准库,但符号名解杬不岀来,改连接阶段通不过了现 在用 已经编译成功了,默认输出为。现在来试着运行一下: 咦,怎么回事?原来虽然链接时链接器( )找到了动态库 ,但动態 加载器 般是 却没找到再来看看的输出 果然如此,看到没有 为我们提供了两种解决方法 可以把当前路径加入 中然后运行 ,或者以当前路径为參数运 行 (要有权限才行) 把当前路径加入环境变量 当然,如果你觉得不会引起混乱的话,可以直接把该库拷入 等位置(无可避免,这样做也 要有权限),這样链接器和加载器就都叫以准确的找到该库了。我们采用第二种方法 哈哈,这下 就可以找到 这个库了现在可以直接运行了 创建静态库 仍使用刚才的 第一步,生成目标文件。 月 第二步把目标文件归档 就是我们所创建的静态库了,简单吧 下面一行命令就是教你如何在程序中链接靜态库的 我们来用命令比较一下用动态库和静态库链接的程序的区别: 正如前面所说,链接器默认会链接动态库(这里是 ),所以只要把上个命令中嘚 参数去掉就可以了。用实川程序验证一下是否按我们的要求生成了可执行文件: 不妨顺便练习一下的用法: ,看来没有冋题,那就比较一下大小先: 力 看到区别了吧,链接静态库的目标程序和链接动态库的程序比起来简育就是一个庞然大物! 这么小的程序,很难看出执行时间的差别,不过为叻完整起见,还是看 的输出吧: 如果程序比较大的话,应该效果会很明显的

}

我要回帖

更多关于 gcc函数修饰 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信