我有一个共享库(bar.so)形式的插件,它链接到一个更大的程序(foo).foo和bar.so都依赖于相同的第三方库(baz),但是他们需要将baz的实现完全分开.所以当我链接foo(使用提供的目标文件和档案)时,我需要它忽略bar.so中的任何baz使用,反之亦然.
现在,如果我链接foo与--trace-symbol=baz_funbaz_fun是其中一个有问题的符号,我得到以下输出:
bar.so: definition of baz_fun
foo/src.a(baz.o): reference to baz_fun
Run Code Online (Sandbox Code Playgroud)
我相信这告诉我foo正在引用bar.so中的baz_fun(执行foo确认了这一点).
我试过的解决方案:
objcopy以"本地化"感兴趣的符号:objcopy --localize-symbols=local.syms bar.so其中local.syms包含所有感兴趣的符号.我想我可能只是在这里感到困惑,也许"本地"并不意味着我认为这意味着什么.无论如何,我从上面的链接获得相同的输出.我应该注意,如果我nm在bar上运行该工具,那么在使用objcopy所有符号之前,有一个T标志(大写表示全局),并且在objcopy他们有一个t指示它们现在是本地的之后.所以看来我使用objcopy得当.-fvisibility=hidden但是由于一些其他方面的限制,我需要使用GCC 3.3这似乎并不支持该功能.我可能能够升级到更新版本的GCC,但是希望确认使用此标志进行编译将有助于我走向这条道路.其他注意事项:
我有一个本机DLL,它是一个不同应用程序的插件(我基本上没有控制权).一切正常,直到我链接一个额外的.lib文件(将我的DLL链接到另一个名为的DLL ABQSMABasCoreUtils.dll).此文件包含我想要使用的父应用程序中的一些其他API.我甚至没有编写任何代码来使用任何导出的函数,但只是链接在这个新的DLL中导致问题.特别是,当我尝试运行该程序时,我收到以下错误:
应用程序无法正确初始化(0xc0000025).单击"确定"以终止该应用程序.
我相信我已经读到某处,这通常是由于DllMain函数返回FALSE.此外,以下消息将写入标准输出:
错误:在组件初始化之前尝试进行内存分配
我几乎100%确定此错误消息来自应用程序,并不是某种类型的Windows错误.
再看一下这个(也就是我周围的翻转和翻转我知道的每个开关)我打开了/ MAP链接并在生成的.map文件中找到了这个:
0001:000af220 ??3@YAXPEAX@Z 00000001800b0220 f ABQSMABasCoreUtils_import:ABQSMABasCoreUtils.dll
0001:000af226 ??2@YAPEAX_K@Z 00000001800b0226 f ABQSMABasCoreUtils_import:ABQSMABasCoreUtils.dll
0001:000af22c ??_U@YAPEAX_K@Z 00000001800b022c f ABQSMABasCoreUtils_import:ABQSMABasCoreUtils.dll
0001:000af232 ??_V@YAXPEAX@Z 00000001800b0232 f ABQSMABasCoreUtils_import:ABQSMABasCoreUtils.dll
Run Code Online (Sandbox Code Playgroud)
如果我使用"undname"对这些名称进行未装饰,则会给出以下(相同的顺序):
void __cdecl operator delete(void * __ptr64)
void * __ptr64 __cdecl operator new(unsigned __int64)
void * __ptr64 __cdecl operator new[](unsigned __int64)
void __cdecl operator delete[](void * __ptr64)
Run Code Online (Sandbox Code Playgroud)
我不确定我是否理解ABQSMABasCoreUtils.dll这个.map文件中是否存在任何内容,或者为什么我的DLL甚至试图加载ABQSMABasCoreUtils.dll如果我没有任何引用此DLL的代码.任何人都可以帮我把这些信息放在一起,找出为什么这不起作用?值得我通过"dumpbin"确认父应用程序导入的内容ABQSMABasCoreUtils.dll,因此无论如何都会加载它.我也试过延迟加载我的DLL中的DLL,但这并没有改变结果.
编辑
我进行了双重检查,所涉及的所有文件都是64位.
我想在 Windows 中创建一个静态库 (.lib),可以在后续构建中用作未定义函数的“备份”。
例如,假设我有 foobar.lib,它具有以下定义:
FOO
BAR
Run Code Online (Sandbox Code Playgroud)
我还有一些其他程序,FOO它只定义并且将被构建到一个必须导出的 DLLFOO和BAR. 我希望能够使用 foobar.lib 自动导出BAR生成的 DLL 中的默认定义(并忽略FOOfoobar.lib 中的定义)。
我曾尝试将 foobar.lib 发送到链接器,但出现多个定义的符号错误(/FORCE 应该覆盖它,但强烈警告它可能无法按预期工作)。我也试过使用 /NODEFAULTLIB:foobar.lib 但它完全忽略了库并说BAR是未定义的。
我几乎 100% 肯定有一种方法可以做到这一点,因为我使用一个执行此操作的应用程序 (Abaqus) 来允许用户编写插件,而不必为插件 DLL 定义所有必需的导出。他们不使用 /FORCE 选项。
我知道默认情况下,在编译时会忽略未定义的符号.但是,我也希望它们在运行时被忽略.我需要分发一个使用和不使用MPI运行的.so.我会提前知道它是否是MPI工作,如果不是,我将不会进行任何MPI_*调用.如果它不是MPI运行,我需要应用程序不关心它无法解析MPI_*符号.
这可能吗?我本来可以发誓我之前做过这件事,但是我无法让它发挥作用.我每次运行时都会立即得到以下内容,即使我的代码中的逻辑永远不会允许引用该符号:
undefined symbol: hpmp_comm_world
Run Code Online (Sandbox Code Playgroud)
为了我的价值,我使用英特尔Fortran编译器来构建.so文件.
编辑
我找到了链接器标志:"-z lazy",它应该在调用函数时解析函数的引用,这就是我想要的.这不能解决我的问题,但是hpmp_comm_world是一个变量 - 而不是一个函数.这应该有所作为吗?