Я хотел бы исследовать первый
4 байта памяти void-указатель
указывает, чтобы увидеть, является ли это
адрес действующего vtable.
Вы можете сделать это, но у вас нет никаких гарантий, что это сработает. Вы даже не знаете, будет ли void * указывать на vtable. В прошлый раз, когда я изучал это (5+ лет назад), я считаю, что какой-то компилятор хранил указатель vtable до адреса, на который указывает экземпляр *.
Я знаю, что это платформа, может быть, даже
компилятором конкретной версии,
Это также может быть специфично для параметров компилятора, в зависимости от того, какую оптимизацию вы используете и т. Д.
но это могло бы помочь мне в
приложение вперед, и избавиться
из всех пустых указателей над
ограниченный период времени (скажем, 3
лет).
Это единственная опция, которую вы можете видеть для продвижения приложения вперед? Вы рассматривали других?
Есть ли способ получить список всех
vtables в приложении,
Нет: (
или способ проверить, есть ли указатель
указывает на действительный vtable,
Нет стандартного способа. Что вы можете сделать, это открыть некоторые указатели классов в вашем любимом отладчике (или преобразовать память в байты и записать ее в файл), сравнить ее и посмотреть, имеет ли это смысл. Тем не менее, у вас нет никаких гарантий, что какие-либо ваши данные (или другие указатели в приложении) не будут выглядеть достаточно похожими (при преобразовании в байты), чтобы перепутать любой код, который вам нравится.
и указывает ли этот экземпляр на
vtable наследуется от известной базы
класс
Нет снова.
Вот несколько вопросов (возможно, вы их уже рассмотрели). Ответы на них могут дать вам больше возможностей или предложить другие идеи:
насколько велика база кода? Реально ли вводить глобальные изменения или для этого нужно распространить функциональность?
Обрабатываете ли вы все указатели единообразно (то есть: есть ли в вашем исходном коде общие точки, где вы можете подключить и добавить свои собственные метаданные?)
что вы можете изменить в своем исходном коде? (Если у вас есть доступ к подпрограммам выделения памяти или вы можете, например, подключить свои собственные, вы можете подключить свои собственные метаданные).
Если разные типы данных приводятся к пустоте * в различных частях вашего кода, как вы решите позже, что находится в этих указателях? Можете ли вы использовать код, который различает пустоту *, чтобы решить, являются ли они классами или нет?
Допускает ли ваша кодовая база методологии рефакторинга? (рефакторинг в маленьких итерациях, путем добавления альтернативных реализаций для частей вашего кода, затем удаления начальной реализации и тестирования всего)
Редактировать (предлагаемое решение):
Выполните следующие шаги:
определить метаданные (базовый) класс
замените ваши подпрограммы выделения памяти на пользовательские, которые просто ссылаются на стандартные / старые подпрограммы (и убедитесь, что ваш код все еще работает с пользовательскими подпрограммами).
при каждом выделении выделите the requested size + sizeof(Metadata*)
(и убедитесь, что ваш код все еще работает).
замените первые sizeof(Metadata*)
байтов вашего выделения стандартной последовательностью байтов, которую вы можете легко проверить (я неравнодушен к 0xDEADBEEF: D). Затем верните [allocated address] + sizeof(Metadata*)
в приложение. При освобождении возьмите полученный указатель, уменьшите его на `sizeof (Metadata *), затем вызовите системную / предыдущую подпрограмму для выполнения освобождения. Теперь у вас есть дополнительный буфер, выделенный в вашем коде, специально для метаданных при каждом выделении.
В тех случаях, когда вам нужно иметь метаданные, создайте / получите указатель класса метаданных, а затем установите его в зоне 0xDEADBEEF. Когда вам нужно проверить метаданные, reinterpret_cast<Metadata*>([your void* here])
, уменьшите их, затем проверьте, является ли значение указателя 0xDEADBEEF (без метаданных) или что-то еще.
Обратите внимание, что этот код должен присутствовать только для рефакторинга - для производственного кода он медленный, подвержен ошибкам и, как правило, другие плохие вещи, которые вы не хотите, чтобы ваш рабочий код был. Я бы сделал весь этот код зависимым от некоторого макроса REFACTORING_SUPPORT_ENABLED
, который никогда не позволил бы вашему классу метаданных увидеть свет рабочего выпуска (возможно, за исключением тестовых сборок).