在C++中创建类库时,可以在动态(.dll,.so)和静态(.lib,.a)库之间进行选择.它们之间有什么区别,何时适合使用哪种?
在某些情况下,是否有任何令人信服的性能原因选择静态链接而不是动态链接?我已经听过或读过以下内容,但我对这个问题的了解不足以保证它的真实性.
1)静态链接和动态链接之间的运行时性能差异通常可以忽略不计.
2)(1)如果使用使用配置文件数据优化程序热路径的配置文件编译器,则不成立,因为使用静态链接,编译器可以优化代码和库代码.通过动态链接,您的代码可以进行优化.如果大部分时间都花在运行库代码上,那么这可能会产生很大的不同.否则,(1)仍然适用.
我正在尝试创建一个用Go程序编写的静态对象与C程序(比如内核模块或其他东西).
我已经找到了关于从Go调用C函数的文档,但是我没有找到关于如何走另一条道路的文档.我发现它是可能的,但很复杂.
这是我发现的:
有任何人对此有经验吗?简而言之,我正在尝试创建一个完全用Go编写的PAM模块.
我觉得很奇怪-Wl,-Bstatic,以便告诉gcc我想要静态链接哪些库.毕竟我gcc直接告诉所有关于链接库的信息(-Ldir,-llibname).
是否可以直接告诉gcc驱动程序哪些库应该静态链接?
澄清:我知道如果某个库只存在于静态版本中,它将在没有它的情况下使用它-Wl,-Bstatic,但我想暗示gcc更喜欢静态库.我也知道直接指定库文件会链接它,但我更喜欢保持包含静态和动态库的语义相同.
我试图理解当具有全局变量和静态变量的模块动态链接到应用程序时会发生什么.通过模块,我的意思是解决方案中的每个项目(我使用visual studio工作很多!).这些模块内置于*.lib或*.dll或*.exe本身.
我知道应用程序的二进制文件包含数据段中所有单个转换单元(目标文件)的全局和静态数据(如果是const,则只读取数据段).
当此应用程序使用带有加载时动态链接的模块A时会发生什么?我假设DLL有一个全局和静态的部分.操作系统是否加载它们?如果是这样,他们在哪里被加载?
当应用程序使用带有运行时动态链接的模块B时会发生什么?
如果我的应用程序中有两个使用A和B的模块,则是如下所述创建的A和B的全局变量的副本(如果它们是不同的进程)?
DLL A和B是否可以访问应用程序全局变量?
(请说明你的理由)
引自MSDN:
在DLL源代码文件中声明为全局的变量被编译器和链接器视为全局变量,但加载给定DLL的每个进程都获得其自身的DLL全局变量副本.静态变量的范围仅限于声明静态变量的块.因此,默认情况下,每个进程都有自己的DLL全局变量和静态变量.
从这里:
当动态链接模块时,可能不清楚不同的库是否有自己的全局变量实例或者是否共享全局变量.
谢谢.
我一直在想.我知道编译器会将您编写的代码转换为二进制文件,但链接器的作用是什么?对我来说,它们一直是个谜.
我粗略地理解'链接'是什么.当对库和框架的引用添加到二进制文件时.除此之外我什么都不懂.对我来说它"只是有效".我也理解动态链接的基础知识,但没有太深入.
有人可以解释这些条款吗?
我想使用改变可执行文件的rpathinstall_name_tool,但我无法弄清楚rpath现在是什么.install_name_tool需要在命令行上给出旧的和新的rpath.我可以使用什么命令在macOS下打印可执行文件的rpath?
编译静态链接静态库的共享对象时遇到了很多问题.此问题仅出现在x84_64平台上.在x86_32上进行相同的编译工作时,我没有任何问题.
也许这是一个特定于操作系统的GCC配置,但我的研究表明它是如何在x86_64平台上运行GCC的.无论如何,我在Ubuntu 10.04 x86_64上使用gcc 4.4.3.
问题是如何解决的?...确保使用-fPIC编译所有静态库依赖项.
问题1: -fpic和-fPIC之间有什么区别(显然-fPIC会在x86上生成更多指令)?为什么后一种类型在x86_64上下文中更相关?
问题2:我的假设是,当您链接静态代码时,您在链接时将函数硬连接到二进制文件中,为什么它需要"位置无关代码"机制提供的间接级别?
问题3:现在如果x86不需要-fpic/-fPIC来链接共享对象与静态存档,为什么在x86_64中需要它?
问题4:即使需要,为什么不隐式提供?我认为突破性变化应该是一个很大的禁忌
gcc compilation dynamic-linking gnu-toolchain static-linking
我所做的
在为Linux编写共享库时,我倾向于关注重定位,符号可见性,GOT/PLT等.
适用时,我试图避免在同一个库中的函数相互调用时调用PLT存根.例如,让我们说一个共享对象提供了两个公共函数- foo()和bar()(或者那些能够通过用户调用).bar()但是,该功能也会调用foo().所以我在这种情况下做的是:
_foo()和_bar()具有私有可见功能.foo()和bar()弱别名._foo()_bar()这样,共享对象中的代码永远不会使用弱符号.它只直接调用本地函数.例如,在_bar()调用时,它会_foo()直接调用.
但是用户并不知道_*函数,并且总是使用相应的弱别名.
我是怎么做的
在Linux中,这是通过使用以下构造实现的:
extern __typeof (_NAME) NAME __attribute__(weak, alias("_NAME"));
Run Code Online (Sandbox Code Playgroud)
问题
不幸的是,这对OS X不起作用.我对OS X或其二进制格式没有深入的了解,所以我喋喋不休地发现了一些弱函数的例子(比如这个),但是那些并不完全与你可以有一个弱符号相同,但不是一个弱符号,它是DSO本地函数的别名.
可能解决方案
目前,我刚刚禁用了此功能(使用宏实现),因此所有符号都是全局符号并具有默认可见性.我现在想到实现同样目的的唯一方法是让所有_foo函数具有私有可见性,并具有foo默认可见性的相应函数并调用它们的"隐藏"对应物.
更好的方法?
但是,这需要更改大量代码.因此,我宁愿不去那里,除非真的没有别的办法.
那么什么是关闭OS X替代或获得相同语义/行为的最简单方法?
dynamic-linking ×10
c++ ×5
linker ×5
c ×3
gcc ×2
macos ×2
c# ×1
command-line ×1
compilation ×1
darwin ×1
dll ×1
global ×1
go ×1
linux ×1
performance ×1
terminal ×1