Изменить адрес функции-члена в C ++ - PullRequest
1 голос
/ 03 марта 2010

в C ++, я могу легко создать указатель на функцию, взяв адрес функции-члена. Однако возможно ли изменить адрес этой локальной функции?

т.е. скажем, у меня есть funcA () и funcB () в одном классе, определенные по-разному. Я пытаюсь изменить адрес funcA () на адрес funcB (), чтобы во время выполнения вызов funcA () фактически приводил к вызову funcB (). Я знаю, это ужасно, но мне нужно это сделать, спасибо!

EDIT ----------

Справочная информация о том, что я пытаюсь сделать:

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

Кроме того, меня интересует тема из технического любопытства, так как в процессе попыток взломать эту проблему я довольно много узнаю о том, как такие вещи, как генерация кода и поиск функций, работают под капюшон, который у меня не было возможности выучить в школе, только что закончив 2-й курс университета. Я не уверен, что мне когда-нибудь будут преподавать такие вещи в школе, потому что я учусь на компьютере, а не на CS.

Вернуться к теме Методы funcA () и funcB () действительно имеют одинаковую сигнатуру, поэтому проблема в том, что я могу получить только адрес функции, используя оператор &? Буду ли я прав, говоря, что я не могу изменить адрес функции или заменить содержимое по этому адресу, не повреждая части памяти? Будет ли DLL-инъекция хорошим подходом для такой ситуации, если функции экспортируются в dll?

Ответы [ 7 ]

4 голосов
/ 03 марта 2010

Нет. Функции скомпилированы в исполняемый файл, и их адрес фиксируется в течение всего времени жизни программы.

Самая близкая вещь - это виртуальные функции. Приведите нам пример того, чего вы пытаетесь достичь, обещаю, что есть лучший способ.

1 голос
/ 03 марта 2010

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

1 голос
/ 03 марта 2010

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

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

1 голос
/ 03 марта 2010

Это невозможно сделать так, как вы это описываете. Единственный способ изменить цель для статически связанного вызова - это изменить фактический исполняемый код вашей программы. Язык C ++ не имеет функций, которые могли бы достичь этого.

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

0 голосов
/ 03 марта 2010

Это просто!

Для

во время выполнения вызов funcA () фактически приводит к вызову funcB ().

запись funcA() аналогично следующему:

int funcA( int a, int b) {
  return funcB( a, b );
}

: -)

0 голосов
/ 03 марта 2010

Вы не можете делать то, что хотите делать напрямую. Тем не менее, вы можете достичь аналогичного результата с некоторыми немного другими критериями, используя что-то, с чем вы уже знакомы - указатели на функции. Рассмотрим:

// This type could be whatever you need, including a member function pointer type.
typedef void (*FunctionPointer)();

struct T {
   FunctionPointer Function;
};

Теперь вы можете установить Function член для любого данного T экземпляра и вызывать его. Это настолько близко, насколько вы можете разумно получить, и я предполагаю, что, поскольку вы уже знаете о функциональных указателях, вы уже знаете об этом решении.

Почему бы вам не отредактировать свой вопрос с более полным описанием проблемы, которую вы пытаетесь решить? На самом деле это звучит так, будто вы пытаетесь сделать что-то ужасное.

0 голосов
/ 03 марта 2010

Я вполне уверен, что это невозможно в чистом C ++. C ++ не является динамическим языком.

...