链接可执行文件时静态库符号丢失

3
我正在尝试将一个静态创建的.a库与另一段C代码链接起来。然而,在最终的可执行文件中,当使用nm命令查看时,会发现缺少几个符号(函数名)。这是因为链接器(调用gcc)正在剥离那些在与库链接的另一段C代码中未被引用的符号。我想通过nm命令找到的函数符号在.a库中是可见的。如何使链接器不会剥离这种被省略的符号?
3个回答

1
通常,链接器会剥离其他符号 - 主要是为了:
  • 减小可执行文件的最终大小
  • 加快程序的执行速度
这里有两种思路:
  • 当您在gcc命令行中使用选项-O时,即优化代码,因此所有调试信息都被剥离,因此链接器将自动执行相同操作。
  • 当您在gcc命令行中使用选项-g时,它包括所有调试信息,以便可执行文件可以在保留符号的情况下在调试器下加载。
本质上,这两者是互斥的 - 您不能同时拥有两者。
因此,这取决于您使用哪些开关才会发生这种情况。通常,-g开关用于内部调试和测试,以进行公共发布之前。相反,类似于-O2的东西使编译器足够聪明,以生成被认为是优化的可执行文件,例如删除死变量,展开循环等。
希望这可以帮助您并给您提示。

事实上,如果我没记错的话,使用Borland编译器(我想是3.1和5.5)时,如果使用printf并链接浮点数,它会抱怨因为代码中没有推动链接工作的指示,解决方法是包含一个引用浮点数的虚拟函数..有人可以支持我的说法吗? - t0mm13b
你确定吗? 我通常使用-g和-O2,以便在发布模块中即使有调试符号。这会导致发布模块被优化,但仍然具有使“核心文件”可读并且对于死后调试非常有用的符号。 我的意思是:我认为它们不是互斥的(我已经使用这些标志多年了...),但如果不需要,我同意这可能是浪费的。 - Mr.Gate

1
通常情况下,您需要在应用程序中调用一些注册功能来生成此类引用。当然,如果您没有访问第一个库的代码,则只能像tommieb75所描述的那样使用-g选项。

1

使用gcc编译时加上-dynamic参数,可以强制编译器包含所有符号。但请确保这真的是你想要的,因为这样很浪费。

对于一些静态工厂模式可能会有用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接