Вопрос

В моем приложении у меня довольно некоторые пустоты (это из-за исторических причин, приложение было изначально написано в чистом C). В одном из моих модулей я знаю, что пустоты указывают на экземпляры классов, которые могут наследовать из известного базового класса, но я не могу быть на 100% в этом. Поэтому делать Dynamic_cast на пустоте-указателю может дать проблемы. Возможно, пустота-указатель даже указывает на простоту (так что нет VPTR в структуре).

Я хотел бы исследовать первые 4 байта памяти, который указывает, чтобы увидеть, является ли это адрес действительного VTable. Я знаю, что это платформа, может быть, даже компилятор-версия, но это может помочь мне в перемещении приложения вперед и избавиться от всех пустотехников в течение ограниченного периода времени (скажем, 3 года).

Есть ли способ получить список всех VTables в приложении или способе проверки того, указывает ли указатель на действительный VTable, и этот экземпляр указывает на VTable наследует из известного базового класса?

Это было полезно?

Решение

Я хотел бы исследовать первые 4 байта памяти, который указывает, чтобы увидеть, является ли это адрес действительного VTable.

Вы можете сделать это, но у вас нет гарантий, вообще это будет работать. У даже не знаю, если пустота * укажет VTable. В прошлый раз я посмотрел в это (5+ лет назад), я считаю, что какой-то компилятор сохранил указатель VTable до Адрес указан на экземпляр *.

Я знаю, что это платформа, может быть, даже компилятор-версия,

Это также может быть компилятором-параметры Specific, в зависимости от того, какие оптимизации вы используете и так далее.

Но это может помочь мне переместить заявку вперед и избавиться от всех недействительных указателей в течение ограниченного периода времени (скажем, 3 года).

Это единственный вариант, который вы можете увидеть для перемещения приложения вперед? Вы считали других?

Есть ли способ получить список всех VTBable в приложении,

Нет :(

или способ проверить, указывает ли указатель на действительный VTable,

Нет стандартного способа. То, что вы можете сделать, это открыть указатели в своем любимом отладчике (или отставьте память в байты и введите его в файл) и сравните его и посмотрите, имеет ли это смысл. Даже так, у вас нет никаких гарантий, что любой из ваших данных (или других указателей в приложении) не будет выглядеть достаточно похожими (при отливамся как байты), чтобы запутать любой код, который вам нравится.

И этот экземпляр указывает на VTable наследует из известного базового класса?

Нет снова.

Вот несколько вопросов (вы, возможно, их уже рассмотрели). Ответы на них могут дать вам больше вариантов, или могут дать нам другие идеи, чтобы предложить:

  • Насколько велика кодовая база? Это возможно, чтобы ввести глобальные изменения, или является функциональностью распространения для этого?

  • Вы относитесь к всем указателям равномерно (то есть: есть ли общие точки в исходном коде, где вы можете подключить и добавить свои собственные метаданные?)

  • Что вы можете изменить на своем Sourcecode? (Если у вас есть доступ к подпрограммам распределения памяти или может подключиться к своему собственному, например, вы сможете подключить собственные метаданные).

  • Если разные типы данных отлиты от void * в различных частях вашего кода, как вы решите позже, что на этих указателях? Можете ли вы использовать код, который дискриминирует пустоту *, чтобы решить, являются ли они классы или нет?

  • Ваше кодовое основание позволяет методологии рефакторизации? (рефакторинг в небольших итерациях, подключив альтернативные реализации для частей вашего кода, а затем удалить начальную реализацию и тестирование всего)

Редактировать (предложенное решение):

Сделать следующие шаги:

  • Определите класс метаданных (базы)

  • Замените свои процедуры распределения памяти с помощью пользовательских, которые просто относятся к стандартным / старым процедурам (и убедитесь, что ваш код все еще работает с обычными процедурами).

  • на каждом распределении выделить the requested size + sizeof(Metadata*) (и убедитесь, что ваш код все еще работает).

  • заменить первый sizeof(Metadata*) Байты вашего распределения со стандартной последовательностью байты, на которую вы можете легко проверить (я частично до 0xDeadbeef: D). Затем вернуться [allocated address] + sizeof(Metadata*) к заявке. Приделка, возьмите полученную указатель, уменьшите его «SizeOf (Metadata *), затем вызовите систему / предыдущую рутину для выполнения DealLocation. Сейчас, У вас есть дополнительный буфер, выделенный в вашем коде, специально для метаданных на каждом распределении.

  • В случаях вы заинтересованы в том, чтобы иметь метаданные для создания / получения указателя класса метаданных, затем установите его в зоне 0xDeadbeef. Когда вам нужно проверить метаданные, reinterpret_cast<Metadata*>([your void* here]), уменьшите его, а затем проверьте, является ли значение указателя 0xDeadbeef (no метаданных) или что-то еще.

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

Другие советы

Я бы сказал, что это невозможно без связанной ссылки (заявление заголовка).

Если вы хотите заменить эти указатели пустоты на правильный тип интерфейса, вот то, что я думаю, чтобы автоматизировать его:

  1. Пройдите через вашу кодовую базу, чтобы получить список всех классов, имеющих виртуальные функции, вы можете сделать это быстро, написав сценарий, как Perl

  2. Напишите функцию, которая принимает пустоту * указатель в качестве ввода, и итерации по поводу этих классов пытаются Dynamic_Cast, и регистрируйте информацию о том, если это удалось, например, тип интерфейса, строка

  3. Вызовите эту функцию в любом месте, где вы использовали void * Указатель, может быть, вы можете обернуть его макросом, чтобы вы могли получить файл, линейную информацию легко

  4. Запустите полную автоматизацию (если у вас есть) и проанализируйте вывод.

Чем проще будет перегружать operator new для вашего конкретного базового класса. Таким образом, если вы знаете, что ваши пустоты * указатели, находятся на кучи объектов, то вы также можете с уверенностью на 100% определить, указывают ли они на ваш объект.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top