1

概念の理解度をテストする演習として、仮想テーブルのアドレスから仮想関数を呼び出しています。しかし、仮想メソッド テーブルの理解に突破口ができたと思った途端、まったく理解できない別の問題に遭遇しました。

以下のコードCarでは、メンバー変数 x と 2 つの仮想関数 first と second を含む というクラスを作成しました。ここで、仮想テーブルをハッキングして、これら 2 つの仮想メソッドを呼び出します。最初の関数は正しい答えを返しますが、2 番目の関数は、初期化された値ではなく、ランダムな値またはガベージを返します。

#include <cstdio>

class Car
{
private:
    int x;

    virtual int first()
    {
        printf("IT WORKS!!\n");
        int num = 5;
        return num;
    }
    virtual int second()
    {
        printf("IT WORKS 2!!\n");
        //int num  = 5;
        return x;
    }


public:

    Car(){
        x = 2;
    }
};

int main()
{
    Car car;
    void* carPtr = &car;
    long **mVtable =(long **)(carPtr);

    printf("VTable: %p\n", *mVtable);
    printf("First Entry of VTable: %p\n", (void*) mVtable[0][0]);
    printf("Second Entry of VTable: %p\n", (void*) mVtable[0][1]);

    if(sizeof(void*) == 8){
        printf("64 bit\n");
    }

    int (*firstfunc)() = (int (*)()) mVtable[0][0];
    int x = firstfunc();    

    int (*secondfunc)() = (int (*)()) mVtable[0][1];
    int x2 = secondfunc();

    printf("first: %d\nsecond: %d", x, x2);
    return 0;
}

誰かが私が間違っていることを指摘できれば幸いです。また、これはコンパイラによって動作が異なるため、c++14 を使用してhttp://cpp.sh/でテストしています。

そのコード出力は、「ガベージ」の 2 番目の出力が変更される可能性がある場合に出力されます。

VTable: 0x400890
First Entry of VTable: 0x400740
Second Entry of VTable: 0x400720
64 bit
IT WORKS!!
IT WORKS 2!!
first: 5
second: -888586240 
4

3 に答える 3