Как работают указатели на функции в C?- конкретный пример - PullRequest
0 голосов
/ 25 октября 2018

Итак, я понимаю, что этот вопрос задавался ранее.Я до сих пор не понимаю следующее:

#include <stdio.h>

main() {
    volatile int (*fp)();
    char buffer[64];
    fp = 0;

    if(fp){
        printf("Buffer Overflow, jumping to %p", fp);
        fp();
    }
}

Первая строка объявляет указатель функции fp.В третьей строке указывается значение 0, которое должно быть эквивалентно адресу 0 (&0), указателю функции.Теперь это содержимое адреса памяти, на который указывает указатель.Поэтому оператор if никогда не должен становиться правдой.Тем не менее, должно стать правдой, оно будет исполненоЕсли это было выполнено, функция printf печатает адрес, который теперь хранится в моем указателе fp.

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

Ответы [ 2 ]

0 голосов
/ 25 октября 2018

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

Но целью кода является то, что , если fp каким-то образом изменить на значение, отличное от NULL (то есть установить на указатель на функцию), тогда этокод напечатает это значение указателя, а затем выполнит указанную функцию .

0 голосов
/ 25 октября 2018

Этот «код» предполагает нечто, гарантированное стандартом C.

fp = 0; - назначает fp с указателем NULL (и выдает предупреждение)

Вы должны использовать fp = NULL; или если вы не уверены во внутреннем представлении указателя NULL в памяти (в вашей реализации нули) fp = (int (*)())0;

Теперь программа предполагает, что fp будет помещен после буфера, который не гарантирован в C. Реализация может упорядочивать переменные по-своему.

Но даже если предположить этот порядок - если буфер записан вне границ (но он будет работать, только если это будет меньше, чем sizeof (fp) и записанные данные не равны нулю), fp станет неНОЛЬ.Но вы не можете вызвать его, так как он будет содержать случайный адрес, и ваша программа вылетит

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