4

ご存知のように、仮想関数テーブル ポインターは通常、インスタンスの最初の 4 バイトに格納されます。しかし、指定された ELF ファイルのどこに仮想関数テーブルが格納されているのか、非常に興味があります。テスト用に以下のプログラムを書き、readelf -s a.outコマンドでELFファイルのシンボルテーブルを取得したのですが、「vtable」とかそういうのが見つかりません。

#include <iostream>
#include <stdio.h>
using namespace std;

typedef void (*fun_pointer)(void);
class Test
{
public:
    Test()
    {
        cout<<"Test()."<<endl;
    }
    virtual void print()
    {
        cout<<"Test::Virtual void print()."<<endl;
    }
    virtual void print2()
    {
        cout<<"Test::Virtual void print2()."<<endl;
    }


};

class TestDrived:public Test
{
public:
    TestDrived()
    {
        cout<<"TestDrived()."<<endl;
    }
    virtual void print()
    {
        cout<<"TestDrived::virtual void print()."<<endl;
    }
    virtual void print2()
    {
        cout<<"TestDrived::virutual void print2()."<<endl;
    }

    void GetVtblAddress()
    {
        cout<<"vtbl address:"<<(int*)this<<endl;
    }
    void GetFirstVtblFunctionAddress(void)
    {
        cout<<"First function address in vtbl:"<< (int*)*(int*)this+0;
    }
    void GetSecondVtblFunctionAddress(void)
    {
        cout<<"First function address in vtbl:"<< (int*)*(int*)this+2<<endl;    //my os is 64bit   //linux, if you use 32bit OS, please replace the "this+2" with "this+1"
    }
    void CallFirstVtblFunction()
    {
        fun = (fun_pointer)* ( (int*)*(int*)this+0 );
        fun();
    }
    void CallSecondVtblFunction()
    {
        fun = (fun_pointer)* ( (int*)*(int*)this+2 );  //my os is 64bit   
        //linux, if you use 32bit OS, please replace the "this+2" with "this+1"
        fun();
    }
private:
    fun_pointer fun;   
};


int main()
{
    cout<<"sizeof(int):"<<sizeof(int)<<"sizeof(int*)"<<endl<<sizeof(int*)<<endl;
    fun_pointer fun = NULL;
    TestDrived a;
    a.GetVtblAddress();
    a.GetFirstVtblFunctionAddress();
    a.GetSecondVtblFunctionAddress();
    a.CallFirstVtblFunction();
    a.CallSecondVtblFunction();
    return 0;
}
4

2 に答える 2

2

仮想テーブルは ELF ファイルのセクション .rodata に格納され、それに対応するセグメントがメモリにロードされます。

于 2015-01-03T16:50:05.557 に答える
0

訂正注: 対応するセグメントがメモリにロードされます。→対応するセグメントがメモリにロードしています。セグメントは実行可能ファイルではなく、メモリ内の概念であるためです。人々が助けを得るためにそれを読むとき、いくつかの混乱する部分があるのではないかと心配しています.

于 2021-09-01T14:23:38.463 に答える