如何使 LD 将乘法定义的结构/类视为错误

how to make ld treat Multiply defined structs/classes as an error?

本文关键字:结构 错误 定义 LD 何使      更新时间:2023-10-16

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

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

在此设置中:

void foo();

答.cpp

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

主.cpp

#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 链接很好。 运行代码表明,在这种情况下,链接器选择使用 A.cpp 中的A

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

函数foo()存在于两个对象文件中时,链接器会报告多个定义,但对于结构,它不会。

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

00000000 W A::A()

如何检测此问题?

也许这个问题可以改写为"如何使编译器生成强符号?...

尝试限制inline函数的使用:

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

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

这不是问题,也不是重新定义。这就是C++的工作方式。想想看——你把类定义放在头中(只公开声明要少得多(。标题几乎被复制粘贴到使用它们的每个翻译单元中。在多个 TU 中对同一类有多个定义不会是错误。所以,这不是要解决的问题。

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