4

考虑我的小示例 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()。我知道您可以对我在没有唯一前缀的情况下进行函数调用感到羞耻。你是对的。这是一个错误。我不在乎。这个错误可以被链接器捕获,因此应该被捕获。链接器没有理由不捕捉这个错误。此外,您使用的库可能会导出一些奇怪的意外符号,并且您不一定可以控制其他人的库导出的内容。只有在程序员停下来并着火之前,那个和前缀才能变得如此独特。

4

2 回答 2

1

添加:

-fvisibility=隐藏

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

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

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

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

如果你有兴趣。

于 2012-12-21T16:54:32.867 回答
0

诸如-Wall -Wextra -Wshadow影响源代码分析的编译器标志等选项;显然,您正在使用链接器选项。

但是,由于shutdown()它位于为应用程序保留的命名空间中(并且您甚至没有表明您已经包含了声明 system 的标头shutdown()),因此编译器或链接器无能为力。作为应用程序程序员,您有权创建一个名为shutdown()并调用它的函数。您可以查看诸如 LSB(Linux 标准库)合规性套件之类的东西,以检查您是否没有定义由实现定义的功能。

我不得不追查的最难的错误之一涉及我们代码中的一个函数,该函数恰好与具有不同接口_bind()的系统函数同名。_bind()当我们的函数被系统库的一部分调用时,一切都乱套了。这部分是我们使用为系统保留的名称(不要以 开头的变量或函数名称_)的错误,不幸的是只有一个平台发生名称冲突。我们的系统前缀_bind()解决了这个问题。

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

于 2012-12-21T17:26:01.510 回答