C C ++函数名冲突和崩溃不一致

时间:2012-07-13 20:39:04

标签: c++ function conflict

有人可以解释导致此用户错误导致崩溃不一致的幕后故事。

这是主要功能

#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()函数的名称。

我知道编写这样的代码杂乱无章,并且容易出错。有人可以向我解释为什么代码崩溃不一致吗?

谢谢大家

此致

2 个答案:

答案 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

我的编译器在此抛出错误。要避免的最好方法是使用单独的命名空间或宏保护。