以前にコンパイルしたc ++プログラムがありますが、Jamfilesをいじった後、プログラムはコンパイルされなくなり、ld
はduplicate symbol error
を発行しました。これは、元のJamfileに連続して戻り、bjam clean
を実行し、オブジェクトを手動で削除し、MacO10.6.7でgccフロントエンドのclangからgcc4.2.1に切り替えた後も持続しました。
プログラムの簡単な説明は、main.cpp
と4つのファイルa.h,cpp
とb.h,cpp
があり、これらはmain.o
にリンクされている静的ライブラリにコンパイルされていることです。 main.cpp
とb.cpp
はどちらも、2つの異なる中間ファイルを介して、問題のシンボルoff.h
を含むファイルに依存しますが、a.h
もa.cpp
もいずれにも依存しません。 off.h
への道。
質問する前に、すべてのファイルが複数の定義ガード(#ifndef
、#define
、#endif
)でラップされていることを確認しました。それらが欠落しているファイルを見つけましたが、 off.h
を参照しないでください。さらに重要なことに、b.h
にはoff.h
を参照するものは含まれず、実装b.cpp
のみがoff.h
を参照します。これだけで私は戸惑いました。
混乱を助長するために、off.h
からb.cpp
への参照を削除することができ、予想どおり、正常に再コンパイルされました。ただし、参照を再度追加すると、コンパイルも正常に行われ、オブジェクトファイルをクリーンアップした後もコンパイルが続行されました。特にシンボルが競合してはならないこと、シンボルの重複を防いだこと、以前の/不完全なビルドを取り除いたことを考えると、コンパイルに失敗した理由についてはまだ途方に暮れています。
プログラムを正常にコンパイルできたので、提案をテストするためにプログラムを再現できるとは思えません。しかし、これがどのように発生するのか知りたいのですが、将来この動作に遭遇した場合、私が行ったことを超えた場合、それを修正するために何をすることができますか?
これは多くの場合、単にオブジェクトを宣言するのではなく、ヘッダーファイルでオブジェクトを定義した結果です。考えてみましょう:
h.h:
#ifndef H_H_
#define H_H_
int i;
#endif
a.cpp:
#include "h.h"
b.cpp:
#include "h.h"
int main() {}
これにより、重複するシンボルi
が生成されます。解決策は、ヘッダーファイルでオブジェクトを宣言することです。extern int i;
そしてそれをソースコードファイルの1つだけで定義するには:int i;
。