Как получить индекс каждой виртуальной функции так же, как это делает компилятор? - PullRequest
4 голосов
/ 17 июня 2010

Есть ли какой-нибудь плагин или инструмент, который может читать файл .h (или просто изменять сам Intellisense) и выплевывать каждую функцию и ее индекс таблицы виртуальных функций? Есть шаблон, который мне еще предстоит выяснить, связанный с полиморфизмом, и он становится в 5 раз сложнее, когда вы начинаете иметь 5 или более классов, происходящих друг от друга. Независимо от того, что, однако, компилятор MSVC ++ всегда выдает правильный индекс таблицы виртуальных функций при компиляции вызова виртуальной функции из C ++ в Assembly. Должен быть лучший способ получить этот индекс без загрузки, наведения на разрыв, чтения смещения и переписывания кода, верно?

Спасибо!

Ответы [ 3 ]

8 голосов
/ 17 июня 2010

Используйте скрытую опцию компилятора Microsoft C / C ++ "/ d1 reportAllClassLayout". Это распечатает макет памяти и таблицы всех ваших классов.

0 голосов
/ 14 августа 2011

В MSVC вы не можете просматривать во время выполнения виртуальную таблицу и сравнивать равенство с указанным указателем на функцию-член, поскольку они не совпадают.Один - реальный указатель, другой - указатель, который перенаправляет на настоящий.

Однако с этим компилятором вы можете сделать это во время выполнения с другим обнаруженным мной хаком.

Создать класс (например, IndexFinder), внутри которого вы объявляете столько методов экземпляра, сколько максимальных виртуальных методов вы можете иметь в классе.Каждый из этих методов должен возвращать уникальное целочисленное значение, начиная с 0 до максимального значения.

Создайте поддельную таблицу виртуальных методов и сохраните ваши указатели методов так, чтобы возвращаемое ими целое число совпадало с индексом, в котором вы их храните (метод, который возвращает 0, будет первым в вашей поддельной таблице).Когда вы хотите найти индекс любого виртуального метода, вы должны выполнить грязное приведение указателя на член метода к указателю на метод IndexFinder.

Принцип прост: для виртуальных методов компилятор генерирует код, который перенаправляетк реальному методу, используя vtable с хорошим индексом.Когда вы заменили созданный компилятором vtable на поддельный, он перейдет к вашему, а не к предполагаемому.Поскольку ваш метод возвращает индекс, внутри которого он хранится, вам просто нужно получить возвращение, и у вас есть свой индекс.

Вот код, который является более явным (я повторяю, что хак зависит от компилятора, те, ктоне нравится, не читай ^^).Но я попробовал, он работает отлично, так как это просто перенаправление перенаправления (я ищу трюк с GCC, но пока не нашел).

Возможно, это зависит от соглашения о вызовах, пока я не пробовал его во всех случаях.Одним из преимуществ этого трюка является то, что вам не нужно создавать экземпляр вашего класса, чтобы найти индекс одного из его виртуальных методов.

// In the header .h
class IndexFinder
{
    typedef int (IndexFinder::*method_pointer)();
public:
    template<typename _MethodPtr>
    int getIndexOf(_MethodPtr ptr) { 
        return (reinterpret_cast<IndexFinder*>(&fake_vtable_ptr)->**((IndexFinder::method_pointer*)(&ptr)))() 
    }
protected:
    int method0() { return 0; }
    int method1() { return 1; }        
    int method2() { return 2; }
    int method3() { return 3; }
protected:
typedef method_pointer fake_vtable_t [4]; 
    static fake_vtable_t   fake_vtable;
    void*                  fake_vtable_ptr;  
};

// In the cpp file
IndexFinder::fake_vtable_t IndexFinder::fake_vtable = {
    &IndexFinder::method0 ,
    &IndexFinder::method1 ,
    &IndexFinder::method2 ,
    &IndexFinder::method3 
};
void* IndexFinder::fake_vtable_ptr = &IndexFinder::fake_vtable;

// to use it : 
int index = IndexFinder::getIndexOf(&YourClass::yourVirtualMethod);
0 голосов
/ 17 июня 2010

Вы можете попробовать написать хак, который определяет его для вас - это определяется реализацией, но обычно вы можете найти указатель на таблицу виртуальных функций в начале памяти классов.Если вы будете следовать этой таблице, в памяти будет список указателей функций (но вы не будете знать, сколько их).Однако, выполняя поиск известных вам функций в таблице указателей функций, вы можете определить ее индекс.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...