有人可以解释导致此用户错误导致崩溃不一致的幕后故事。
这是主要功能
#include "foo.h"
inline int Bar(const int &a)
{
...
}
...
int b=Bar(a);
在“foo.C”中还有一个函数副本
inline int Bar(const int &a)
这是问题所在。我不拥有foo.h或foo.C,并且foo.h中没有Bar(int)的声明。
所有东西都可以用旧版本的foo.h和foo.C编译并正常工作
在我的同事更新了他的foo.C中的其他一些函数之后,代码仍然编译得很好但是在执行时它开始崩溃。
通过ddd调试显示,当我的main函数调用Bar()时,它实际上是调用foo.C中的Bar()而不是我自己定义的Bar()。
因为修复是静态我自己的函数或更改我自己的Bar()函数的名称。
我知道编写这样的代码杂乱无章,并且容易出错。有人可以向我解释为什么代码崩溃不一致吗?
谢谢大家
此致
答案 0 :(得分:2)
内联函数仍然具有外部链接。也就是说,它们由编译器发送到相应的目标文件中,并且当链接器链接应用程序时,它认为具有相同签名的所有函数(包括它们的名称和封闭的命名空间)是相同的。由于函数定义为inline
,因此它会随机选择其中一个定义并丢弃另一个定义,而不会出现错误。 (这违反了一个定义规则,根据标准导致未定义的行为。)
要防止出现此问题,请使用匿名命名空间,如下所示:
namespace {
inline int Bar(const int &a)
{
...
}
}
在你的情况下,在foo.C或main中这样做会做到这一点。等效地,您可以添加static
:
static int Bar() {}
如果你是用C语言写的。
使用匿名命名空间或static
关键字使该函数成为转换单元的本地函数,因此链接器不会将其视为外部符号。这样,您可以在不同的翻译单元中拥有任意数量的具有相同签名的函数。
答案 1 :(得分:0)
我认为你正在使用foo定义的Bar函数,因为在你定义自己的Bar函数之前它是通过foo.h #include。
我很惊讶你的编译器没有警告你 重复定义(非法),但如果您已经定义了 #include“foo.h”之前的bar函数应该有错误 被抛出。
此网址表示重新定义内联是非法的 除非内联是相同的:
C static inline function redefinition rules
我的编译器在此抛出错误。要避免的最好方法是使用单独的命名空间或宏保护。