71

Eclipse-CDT を使用して、Ubuntu x64 で C++ プロジェクトをセットアップしています。私は基本的にハローワールドをやっていて、商用のサードパーティライブラリにリンクしています。

ライブラリにリンクされたヘッダー ファイルをインクルードしましたが、まだリンカー エラーが発生します。明らかな問題以外に考えられる問題はありますか (たとえば、正しいライブラリにリンクしていると 99% 確信しています)。

  1. リンク先の静的ライブラリが 64 ビットであることを確認する方法はありますか?
  2. ライブラリに必要なクラス (およびメソッド) があることを確認する方法はありますか?

エクリプス 言います:

ビルド ターゲット: LinkProblem
呼び出し: GCC C++ リンカ
g++ -L/home/notroot/workspace/somelib-3/somelib/target/bin -o"LinkProblem" ./src/LinkProblem.o -lsomelib1 -lpthread -lsomelib2 -lsomelib3
./src/LinkProblem.o: 関数 `main' 内:
/home/notroot/workspace/LinkProblem/Debug/../src/LinkProblem.cpp:17: `SomeClass::close()' への未定義の参照
./src/LinkProblem.o: 関数 `SomeOtherClass' 内:
/home/notroot/workspace/somelib-3/somelib/include/sql/somefile.h:148: `SomeClass::SomeClass()' への未定義の参照
/home/notroot/workspace/somelib-3/somelib/include/sql/somefile.h:148: 「SomeOtherClass の vtable」への未定義の参照
/home/notroot/workspace/somelib-3/somelib/include/sql/somefile.h:151: `SomeClass::~SomeClass()' への未定義の参照
./src/LinkProblem.o: 関数 `~SomeOtherClass' 内:
/home/notroot/workspace/somelib-3/somelib/include/sql/somefile.h:140: 「SomeOtherClass の vtable」への未定義の参照
/home/notroot/workspace/somelib-3/somelib/include/sql/somefile.h:140: `SomeClass::~SomeClass()' への未定義の参照
/home/notroot/workspace/somelib-3/somelib/include/sql/somefile.h:140: `SomeClass::~SomeClass()' への未定義の参照
collect2: ld が 1 つの終了ステータスを返しました
make: *** [LinkProblem] エラー 1
4

12 に答える 12

168

このリンカエラーは通常(私の経験では)、子クラスの仮想関数を宣言でオーバーライドしたが、メソッドの定義を指定していないことを意味します。例えば:

class Base
{
    virtual void f() = 0;
}
class Derived : public Base
{
    void f();
}

しかし、あなたはfの定義を与えていません。クラスを使用すると、リンカエラーが発生します。通常のリンカエラーと同じように、コンパイラはあなたが話していることを知っていたが、リンカは定義を見つけることができなかったためです。メッセージを理解するのは非常に難しいです。

于 2010-08-07T13:06:15.130 に答える
74

これらのメソッドがライブラリの 1 つにあると仮定すると、順序付けの問題のように見えます。

ライブラリを実行可能ファイルにリンクする場合、それらは宣言されている順序で行われます。
また、リンカーは、現在未解決の依存関係を解決するために必要なメソッド/関数のみを受け取ります。後続のライブラリが、オブジェクトに元々必要でなかったメソッド/関数を使用すると、依存関係が失われます。

使い方:

  • すべてのオブジェクト ファイルを取得し、それらを実行可能ファイルに結合します
  • オブジェクト ファイル間の依存関係を解決します。
  • 各ライブラリの順番:
    • 未解決の依存関係を確認し、ライブラリがそれらを解決するかどうかを確認します。
    • その場合は、必要な部分を実行可能ファイルにロードします。

例:

オブジェクトには次が必要です。

  • 開ける
  • 近い
  • バッチ読み取り
  • バッチ書き込み

ライブラリ 1 は以下を提供します。

  • 開ける
  • 近い
  • 読んだ
  • 書きます

Lib 2 が提供する

  • BatchRead (ただし lib1:read を使用)
  • BatchWrite (ただし lib1:write を使用)

このようにリンクされている場合:

gcc -o plop plop.o -l1 -l2

その場合、リンカは読み取りシンボルと書き込みシンボルの解決に失敗します。

しかし、次のようにアプリケーションをリンクすると:

gcc -o plop plop.o -l2 -l1

すると正しくリンクします。l2 は BatchRead と BatchWrite の依存関係を解決しますが、2 つの新しい依存関係 (読み取りと書き込み) も追加します。次に l1 とリンクすると、4 つの依存関係がすべて解決されます。

于 2009-07-07T23:11:57.463 に答える
52

Qt C++ は、QObject から継承するように (つまり、シグナル/スロットを使用できるように) クラスを変更すると、このエラーを表示します。qmake -r を実行すると moc が呼び出され、この問題が修正されます。

ある種のバージョン管理を介して他のユーザーと作業している場合は、.pro ファイルに何らかの変更を加える必要があります (つまり、空白行の追加/削除)。他の全員が変更を取得して make を実行すると、make は .pro ファイルが変更されたことを認識し、自動的に qmake を実行します。これにより、チームメイトがフラストレーションを繰り返すのを防ぐことができます。

于 2011-02-14T18:34:15.500 に答える
14

私にとっての問題はかなりあいまいであることが判明しました。私のクラスは次のようになりました:

//-----------------------------------------
// libbase.h
class base {
public:
   base() { }
   virtual ~base() { }

   virtual int foo() { return 0; }
};
//-----------------------------------------

//-----------------------------------------
// libbase.cpp
#include "libbase.h"
//-----------------------------------------

//-----------------------------------------
// main.h
class derived : public base {
public:
    virtual int foo() ;
};
//-----------------------------------------

//-----------------------------------------
// main.cpp
int main () {
    derived d;
}
//-----------------------------------------

問題はリンカーにあります。私のヘッダー ファイルはライブラリのどこかにありましたが、すべての仮想関数はクラス宣言で「インライン」と宣言されていました。(まだ) 仮想関数を使用するコードがなかったため、コンパイラまたはリンカーは実際の関数本体を配置することを怠っていました。また、vtable の作成にも失敗しました。

このクラスから派生したメイン コードで、リンカはクラスを基本クラスとその vtable に接続しようとしました。しかし、vtable は破棄されていました。

解決策は、次のように、クラス宣言の外で少なくとも 1 つの仮想関数の本体を宣言することでした。

//-----------------------------------------
// libbase.h
class base {
public:
   base() { }
   virtual ~base() ;   //-- No longer declared 'inline'

   virtual int foo() { return 0; }
};
//-----------------------------------------

//-----------------------------------------
// libbase.cpp
#include "libbase.h"
base::~base() 
{
}
//-----------------------------------------
于 2011-05-26T21:06:02.647 に答える
9

Qt4の問題に関しては、上記のqmakemocオプションを使用できませんでした。しかし、それはとにかく問題ではありませんでした。クラス定義に次のコードがあります。

class ScreenWidget : public QGLWidget
{
   Q_OBJECT        // must include this if you use Qt signals/slots
...
};

信号やスロットが定義されていないため、「Q_OBJECT」という行を削除する必要がありました。

于 2011-06-02T07:51:50.757 に答える
8

このエラーメッセージがありました。問題は、ヘッダー ファイルで仮想デストラクタを宣言したことですが、実際には仮想関数の本体が実装されていませんでした。

于 2012-01-09T07:55:32.363 に答える
1

私も今問題に出くわしました。アプリケーションは純粋な仮想インターフェイス クラスを定義し、共有ライブラリを介して提供されるユーザー定義クラスはインターフェイスを実装することになっていました。アプリケーションをリンクするとき、リンカは、共有ライブラリが基本クラスの vtable と type_info を提供せず、他の場所にも見つからないことを訴えました。インターフェイスのメソッドの 1 つを純粋仮想化するのを単に忘れていたことが判明しました (つまり、宣言の最後にある " = 0" を省略しました)。非常に初歩的であり、リンカー診断を根本的な原因。

于 2013-02-15T14:36:35.910 に答える
0

将来の訪問者のためにこれを置きます:

オブジェクトの作成時にエラーが発生した場合、その原因はおそらく仮想関数Exceptionの定義の欠如です。what()

于 2016-10-18T20:56:02.570 に答える
0

Qtで「hello world」などをしようとすると、このエラーメッセージが表示されました。問題は、qt moc (メタ オブジェクト コンパイラ) を正しく実行し、これらの moc によって生成されたファイルを正しくコンパイル + インクルードすることで解消されました。

于 2010-11-03T21:26:48.007 に答える
0

純粋な仮想関数を持つ基本クラスがある場合は、基本クラスのコンストラクターとデストラクターに本体があることを確認してください。そうしないと、リンカーが失敗します。

于 2014-03-24T17:36:53.927 に答える