获取GCC链接器以警告多个函数定义

获取GCC链接器以警告多个函数定义,gcc,warnings,symbols,one-definition-rule,Gcc,Warnings,Symbols,One Definition Rule,以我的小型示例C库为例: #include <external_library.h> void some_function(void) { external_library_call(); // Do other stuff... } #包括 void某些函数(void) { 外部库调用(); //做其他事情。。。 } 它计划使某些函数()可以公开调用。但是,该库不起作用,因为它所需要的外部库碰巧也使用了一个名为some_function()的函数,该函数恰好具

以我的小型示例C库为例:

#include <external_library.h>

void some_function(void)
{
    external_library_call();
    // Do other stuff...
}
#包括
void某些函数(void)
{
外部库调用();
//做其他事情。。。
}
它计划使某些函数()可以公开调用。但是,该库不起作用,因为它所需要的外部库碰巧也使用了一个名为some_function()的函数,该函数恰好具有相同的原型。不过,GCC的链接器并不关心某些函数符号有多少个源。它似乎随机选取一个函数,外部库可能会也可能不会使用我的some_函数()而不是它自己的函数。这太疯狂了。不是因为图书馆不起作用。这个图书馆肯定不能用。更重要的是,符号“some_function”有两个来源,但链接器对此没有做任何处理。你知道,这并没有让我太烦恼,因为我习惯了GCC和C在默认情况下通常是病态的鲁莽。不过,总有办法让链接器在同一个符号有两个来源时警告我。我已经尝试了-Wall-Wextra-Wshadow,但这不会产生任何警告

请注意,-fvisibility=hidden在这里没有帮助,因为两个库都希望导出一些函数()。我知道你可以为我没有唯一前缀的函数调用感到羞耻。你说得对。这是个错误。我不在乎。链接器可以捕获此错误,因此应该捕获。链接器没有理由不抓住这个错误。此外,您正在使用的库可能会导出一些奇怪的意外符号,并且您不必控制其他库导出的内容。只有在程序员停止并着火之前,才能使其和前缀变得如此独特。

添加:

-fvisibility=hidden -可视性=隐藏 添加到您的构建标志。然而,请注意一些注意事项;某些标题可能不希望出现这种情况。在这些情况下,在包含它们之前需要使用pragma:

#pragma GCC visibility push(hidden)
#include <problematic_header>
#pragma GCC visibility pop
#pragma GCC可见性推送(隐藏)
#包括
#布拉格语
除了避免符号冲突之外,还有其他一些好处。见:


如果您感兴趣。

选项,如
-Wall-Wextra-Wshadow
是影响源代码分析的编译器标志;显然,你在寻找一个链接器选项

但是,由于
shutdown()
位于保留给应用程序使用的名称空间中(并且您甚至没有显示您包含了声明系统
shutdown()
)的头),因此编译器或链接器无法做什么。作为应用程序程序员,您有权创建一个名为
shutdown()
的函数并调用它。您可以查看LSB(Linux标准库)遵从性套件之类的东西,以检查您没有定义由实现定义的函数

我曾经追踪到的一个更难的bug涉及代码中的函数
\u bind()
,该函数恰好与具有不同接口的系统函数
\u bind()
同名。当我们的函数被部分系统库调用时,所有的麻烦都爆发了。这部分是因为我们使用了系统保留的名称(不要用
\uuu
启动变量或函数名),不幸的是,只有一个平台有名称冲突。我们的
\u bind()
的系统前缀解决了这个问题


您可以查看C和POSIX标准中的保留名称列表。但是,您会发现
\u t
后缀是保留的,但是带有后缀的类型名也广泛用于用户定义的类型(ab)。您还必须知道该类型的任何给定定义是“来自系统头”(可能是OK),还是来自用户定义头(可能不是OK),或者是“提供缺少系统功能的用户定义头”(边框线)。这变得非常棘手。

关于_bind()错误:我认为这根本不是你的错。在某个时候,链接器一定意识到了_bind()有两种定义。链接器不可能不知道这一点。除非有一些我不熟悉的关于链接器操作的芬尼基细节……实际上,是不是在编译时链接器从未检查它所链接的共享对象的符号表?这是我能想到的唯一解释。即使这样,它仍然有点鲁莽。如果我读对了,我还必须在main()前面添加_属性(可见性(“默认”))来导出它。“对吗?”神秘物理学家,我不这么认为。main()似乎是GCC专门处理的,并且总是导出的。虽然这非常有用,我肯定会使用它,但它并不能解决最初的问题。链接器/known/同一符号有两个单独的实例。为什么它没有停止并传递错误?为什么它选择了一个而不是另一个?标准是什么?如果我需要导出一个符号,并且我想确保它不会与我正在使用的任何其他符号冲突,该怎么办?我仍然认为这个问题没有解决,直到我能让链接器在这种情况下错误地停止。@Enigmatic物理学家在你劫持它并编辑它之前,它确实回答了这个问题。现在它提出了不同的要求。你应该发布一个新问题。它现在问我一直想问的问题。你一开始误解了我,因为我第一次写的时候不清楚。我想我一开始问过这个问题就知道我的意思了。这不是劫持。