如何在Visual-C++中防止静态库符号的“弱”链接?

3
据我的实际测试,在Visual-C++中将静态库(.lib)链接到可执行文件时,如果任何可执行文件 .obj 文件定义了与静态库中的一个符号重复的符号,则静态库中的符号将被默默地忽略确认(Feb 18 '10 at 17:46 Michael Burr)

MSVC曾经的行为是,如果一个符号在.obj文件和.lib文件中都有定义,它会使用.obj文件中的符号而不发出警告。我记得它还处理这样一种情况:当一个符号在多个库中定义时,它会使用列表中第一个库中的符号。

我不能说我已经尝试过这个问题很长时间了,但如果他们改变了这个行为(特别是.obj定义的符号覆盖了.lib文件中的符号),我会感到惊讶。

对VS 2010 RC进行简短的测试表明,我所描述的行为仍然存在。

'Windows Static Library with Default Functions' 对我来说也是一种确认


首先,我希望被证明是错误的,但至少对于一个普通的C++函数来说,似乎就是这样。

其次,有没有什么方法可以防止这种情况发生? 我有一个函数,当任何二进制文件链接到包含此函数的静态库时,我想确认实际使用的是静态库中的版本,而不是其他项目中的残留或其他东西。 (请注意:问题中的Fn是test_suite *init_unit_test_suite(int argc,char * argv []),因此我无法在实践中更改它,因为它来自第三方库。)


(*): 这是Boost.Test的主函数,应该由我们自定义的静态库提供。如果任何开发人员创建一个单元测试项目 - 这些项目通过属性表自动链接到静态库 - 但错误地定义了该函数,则构建应该中断,而不是使用开发人员提供的函数。


特性,而非错误。使用映射文件或链接器的/VERBOSE选项进行诊断。 - Hans Passant
1
@HansPassant - 我从未说过这是一个错误。它只是...并非始终是最优的选择。我不想诊断它,我希望在发生错误时能够得到构建错误提示。 - Martin Ba
1个回答

0

我认为如果您链接到独立的obj文件而不是打包在静态库中,链接器的行为会有所不同。至少您应该会收到一些关于符号重复的警告/错误。

几年前当我需要类似的东西时,我也在MS工具链中找不到它,但有两个MS设备接近并可能很方便:__declspec(selectany)和未记录的#pragma /alternatename。也许链接到一个obj文件并将符号声明为selectany就可以解决问题了?如果不行,也许在exe-obj文件中添加#pragma comment(linker, "/alternatename:_YourSymbol=_DefaultExeSymbol")就可以了。


在发布问题之前,我确实阅读了您的博客文章,但是认为它没有帮助。selectanyalternatename都用于与我想要的相反的目的,即在通常不获取弱链接时获取弱链接。直接链接到对象文件可能会起作用(因为工具链通常可以正常工作),但由于这是第三方库,我目前不知道如何在不使其变得难以维护的情况下访问它。 - Martin Ba
不确定我理解了。你不想在你的exe中强制使用弱链接吗?这正是在重复性情况下导致库定义符号接管的原因。如果我理解正确,你应该能够通过pragma alternatename实现这一点。 - Ofek Shilon
啊,好的。又是一个新的问题。不过我真正喜欢的是在我的可执行文件中根本就没有那个符号并强制实现这一点。你看,这是 Boost.Test 的主函数,应该由我们的自定义静态库提供。如果任何开发人员创建了一个单元测试项目(这些项目通过属性表自动链接到静态库),但错误地定义了该函数,那么构建过程应该会失败,而不是使用开发人员提供的函数。 - Martin Ba
有点取巧,但你仍然可以像上面那样使用#pragma /alternatename,并让_DefaultExeSymbol破坏构建。 - Ofek Shilon

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