Где именно указатели на функции указывают? - PullRequest
13 голосов
/ 28 февраля 2009

Учитывая, что все примитивные типы данных и объекты имеют выделенную память, интуитивно легко представить указатели на эти типы.

Но куда именно указывают функциональные указатели? Учитывая, что инструкции преобразуются в машинный код и находятся в памяти, следует ли нам считать, что они указывают на область памяти, соответствующую началу инструкций функций?

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

Ответы [ 5 ]

29 голосов
/ 28 февраля 2009

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

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

4 голосов
/ 28 февраля 2009

Это указатель кода. Он указывает на адрес функции. По сути, как вы описали. И да, если у вас есть указатели, которые не указывают на то, что вы ожидаете, у вас будут проблемы.

2 голосов
/ 07 марта 2014

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

Самый простой способ для компилятора реализовать указатель на функцию - это адрес памяти функции, и большинство компиляторов делают это таким образом, но в стандарте языка это не указано. Некоторые системы (я думаю, что IBM AS / 400 является примером) хранят дополнительную информацию в функциональных указателях. Компилятор может реализовывать указатели на функции в виде целочисленных индексов в таблице дескрипторов, если требуемая семантика реализована правильно.

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

Не переносимо, учитывая функцию func, вы можете сделать что-то вроде:

printf("Address of func is %p\n", (void*)func);

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

Вы могли бы даже иметь возможность преобразовать указатель функции в unsigned char* и проверить машинный код функции, но выходит далеко за рамки всего, что определено стандартом C.

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

2 голосов
/ 28 февраля 2009

Указатели функций указывают на адрес функции в памяти.

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

0 голосов
/ 28 февраля 2009

Ну, я не уверен, но учитывая, что функции являются инструкциями (ADD, SUB, JMP) и что каждое из них имеет шестнадцатеричные значения, я считаю, что вы не будете изменять функцию, а только инструкцию JMP () .. .

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