让GCC链接器警告多个函数定义

时间:2012-12-21 16:44:27

标签: gcc warnings symbols one-definition-rule

考虑我的小例C库:

#include <external_library.h>

void some_function(void)
{
    external_library_call();
    // Do other stuff...
}

它计划将some_function()公开调用。但是这个库不起作用,因为它需要的外部库也恰好使用了一个名为some_function()的函数,它恰好具有相同的原型。但是,GCC的链接器并不关心some_function符号有多少来源。它随机选择了一个,外部库可能会也可能不会使用我的some_function()而不是它自己的。疯了吧。不是图书馆不起作用的事实。这个库肯定不行。事实上,符号'some_function'有两个来源,但链接器对它没有任何作用。而且你知道,这并不会让我感到太烦心,因为我习惯于GCC和C一般在默认情况下是病态鲁莽的。但是,当有两个相同符号的来源时,必须有一种方法让链接器警告我。我已经尝试过-Wall -Wextra -Wshadow,但这不会产生任何警告。

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

2 个答案:

答案 0 :(得分:1)

添加:

-fvisibility=hidden

到你的构建标志。但请注意一些警告;一些标题可能没有预料到这一点。在这些情况下,您需要在包含它们之前使用pragma:

#pragma GCC visibility push(hidden)
#include <problematic_header>
#pragma GCC visibility pop

除了避免符号冲突之外,还有其他一些好处。参见:

http://gcc.gnu.org/wiki/Visibility

如果您有兴趣。

答案 1 :(得分:0)

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

但是,由于shutdown()位于为应用程序保留的名称空间中(并且您甚至没有显示您已包含声明系统shutdown()的标头),因此编译器或链接器无法做到这一点。您作为应用程序员有权创建一个名为shutdown()的函数并调用它。您可以查看类似LSB(Linux Standards Base)合规性套件的内容,以检查您是否未定义由实现定义的函数。

我遇到的一个较难的错误是在我们的代码中涉及函数_bind(),该函数恰好与具有不同接口的系统函数_bind()同名。当我们的功能被系统库的某些部分调用时,一切都崩溃了。这部分是我们使用保留给系统的名称的错误(不要使用_启动变量或函数名称),不幸的是只有一个平台有名称冲突。我们_bind()的系统前缀解决了这个问题。

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