3

编辑 - 澄清我的问题的目标:我浪费了很多时间来诊断我希望链接器报告的问题,这是由公认的糟糕的编程风格引起的,例如从一个编译单元复制粘贴代码块时会弹出到另一个,并改变它。

我正在寻找一种在编译/链接时检测此问题的方法。

在此设置中:

void foo();

A.cpp

struct A { 
  int values[100];
  A(){ 
    std::cout << __FILE__ << ": A::A()\n";
}};
void foo(){ 
   A a;
}

主文件

#include "A.h"
struct A { 
  double values[100];
  A(){ 
  std::cout << __FILE__ << ": A::A()\n";
}};
int main(){ foo(); }
// void foo(){} ===> this would cause a linker error

我希望链接器报告结构A或至少构造函数A::A()被定义了两次。

但是,g++ 4.4 链接就好了。运行代码显示,在这种情况下,链接器选择使用Afrom A.cpp。

$ g++ -Wall A.cpp main.cpp && ./a.out
A.cpp:3
A.cpp:7
A.cpp:3

当一个函数 foo()出现在两个目标文件中时,链接器会报告一个多重定义,但对于结构,它不会。

编辑:刚刚发现通过使用nm -C *.oAo 和 main.o 都A::A()定义为弱符号。这使它可以从具有相同名称的符号池中“选择”。也许这个问题可以改写为“我怎样才能使编译器生成符号?”......

00000000 W A::A()

我怎样才能检测到这个问题?

4

2 回答 2

2

也许这个问题可以改写为“我怎样才能使编译器生成强符号?”......

尝试限制inline函数的使用:

struct A {
    A();
};

// Inside A.cpp
A::A() { 
    std::cout << __FILE__ << ": A::A()\n";
}

实现更有可能报告未声明的函数inline(包括隐式声明的函数inline,如在类定义中定义的成员)的 ODR 违规,但严格来说,这种诊断从来不需要。

于 2012-05-11T11:24:25.080 回答
0

这不是问题,也不是重新定义。这就是 C++ 的工作原理。想一想——你把类定义放在头文件中(只暴露声明远不常见)。标题几乎被复制粘贴到每个使用它们的翻译单元中。在多个 TU 中具有同一类的多个定义不会是错误的。所以,这不是要解决的问题。

但是,如果在同一名称下定义了不同的类,编译器/链接器应该会抱怨。

于 2012-05-11T11:12:21.513 回答