3

編集--私の質問の目標を明確にする:リンカーが報告することを期待している問題の診断に多くの時間を費やしています.別のものに変更し、それを変更します。

コンパイル/リンク時にこの問題を検出する方法を探しています。

このセットアップでは:

ああ

void foo();

A.cpp

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

main.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

Astructureまたは少なくとも constructorA::A()が 2 回定義されていることをリンカーに報告してもらいたいと思います。

ただし、g++ 4.4 は問題なくリンクします。コードを実行すると、この場合、リンカがAfrom A.cpp の使用を選択したことがわかります。

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

関数 が 2 つのオブジェクト ファイルに存在する場合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ているものを含む) に対して ODR 違反が報告される可能性ははるかに高くなりますが、厳密に言えば、そのような診断は必要ありません。inline

于 2012-05-11T11:24:25.080 に答える
0

それは問題ではなく、再定義ではありません。それがC++の仕組みです。考えてみてください — クラス定義をヘッダーに入れます (宣言だけを公開することはあまり一般的ではありません)。ヘッダーは、それらを使用するすべての翻訳単位にコピー アンド ペーストされます。複数の TU に同じクラスの複数の定義があることはエラーにはなりません。だからといって、解決するものではありません。

ただし、同じ名前で異なるクラスが定義されている場合、コンパイラ/リンカーは文句を言う必要があります。

于 2012-05-11T11:12:21.513 に答える