考虑我的小例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()。我知道你可以说我没有唯一的前缀来进行函数调用。你是对的。这是一个错误。我不在乎。这个错误可以被链接器捕获,因此应该被捕获。链接器没有理由不应该抓住这个错误。此外,您正在使用的库可能会导出一些奇怪的意外符号,并且您不一定能控制其他人的库导出的内容。只有在程序员停止并着火之前,这些和前缀才能变得如此独特。
答案 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),还是来自用户定义的标头(可能不正常),或者是“用户定义的标头提供缺少的系统功能” (边缘)。它变得非常棘手。