2016-12-21 10 views
0

私は仮想テーブルと仮想ポインタを試していました。VTABLEにアクセスすると、定義されていないエラーが発生する

//a simple class 
    class X 
    { 
    public: 
     // fn is a simple virtual function 
     virtual void fn() { cout << "n = " << n << endl; } 
     // a member variable 
     int n; 
    }; 

    int main() 
    { 
    // create an object (obj) of class X 
    X *obj = new X(); 
    obj->n = 10; 

    // get the virtual table pointer of object obj 
    int* vptr = *(int**)obj; 

    __asm__("mov %eax, obj;"); 

    // function fn is the first entry of the virtual table, so it's vptr[0] 
    ((void (*)()) vptr[0])(); 

    // the above should be the same as the following 
    //obj->fn(); 

    return 0; 
    } 

しかし、コンパイラは次のエラーを与えている:

/home/OaVTND/cclnoQaK.o: In function 'main': prog.cpp:(.text.startup+0x26): undefined reference to `obj'
collect2: error: ld returned 1 exit status

私はアセンブリ言語コードに慣れていないよ知っているより多くの私は、次のようでした。私はこれを他の人のコードから借りた。私はgcc-4.9とCentos 7 x64ビットサーバーを使用しています。

+1

インラインasmはいくつかの点で壊れています(インラインアセンブリに入力オペランドとしてobjのアドレスを渡す必要があります。%eaxのランダムな内容をobjに移動します)。あなたが達成しようとしていることは明確ではありません。 – yugr

+0

あなたは__asm__の中で何をしていますか? –

+2

@GreenTree:彼は、オブジェクトのアドレスをEAXにロードすることによって 'this'ポインタを設定しようとしています。コール・ステートメントが誤ってEAXを使用してターゲット・アドレスを計算していない限り、それは問題ありません。 –

答えて

1

objはローカル変数であり、リンケージはありません。シンボルはありません。 オブジェクトをグローバルにしてみてください。

+0

objをグローバルにして再コンパイルしました。しかし、出力は次のとおりです。n = 1076818912これはn = 10にする必要があります。何がうまくいかない。 –

+0

vptr [0]を関数へのポインタにキャストしようとすると、Xへのポインタを受け取り、オブジェクトのアドレスを直接渡します。 –

+0

のyugrsの回答と同様です。 –

1
だけでインラインアセンブラを取り除く

とは

((void (*)(void *)) vptr[0])(&obj); 

警告を行います。私は他のプラットフォーム上のABIの詳細は異なるものになるよう、あなたがのgccのLinux x86_64の上で実行することを前提としています。

+0

これは確かに32ビットWindowsでは動作しません。 'this'ポインタは、通常の引数として渡されません(ECXレジスタに渡されます)。私はx86とx64モードでLinuxがこれをどのように処理するのかわかりません –

+0

GCCがメインコンパイラ(Linuxなど)のほとんどのプラットフォームで動作するというのは、[Itanium ABI](https:// mentorembedded .github.io/cxx-abi/abi.html)があります。 – yugr

+0

@MartinBonner __thiscallを関数型に追加して、MSVSに正式な呼び出し規約を強制的に適用させることができるのだろうかと思います。 – yugr

関連する問題