четверг, 1 октября 2009 г.

Функция без явного определения

Убойный для меня пример.
typedef int (*pf)(int, int);
char c[] = {85,-119,-27,-117,69,12,3,69,8,93,-61,-112};
pf sum = (pf)c; //reinterpret_cast отказывается, поэтому так.
cout << sum(2,3); //Вывод 5.


* This source code was highlighted with Source Code Highlighter.
Теперь sum - функция сложения, являющаяся аналогом этой:
int sum(int a, int b){return a+b;}

Сначала я написал нормальную функцию sum, затем байт за байтом просмотрел ее содержимое в памяти. К сожалению sizeof к функциям неприменим, поэтому я, после sum, определил еще одну функцию, и предположил, что в памяти они тоже рядом. Их адреса различались на 12 байт.

UPD: Одной строкой:
cout << ((int (*)(int, int))"\x55\x89\xE5\x8B\x45\x0C\x03\x45\x08\x5D\xC3\x90")(2,3);

4 комментария:

  1. То есть инструкция "return a+b" в памяти хранится как набор байт? И мы кладем этот набор байт в память, создаем функцию, которая будет указывать на начало этого набора? И значит при ее вызове будет исполнятся код "return a+b". Я правильно понял?
    И так можно сделать с любой функцией?

    ОтветитьУдалить
  2. Ага, все функции хранятся в памяти как набор байт (как и данные). В примере мы искусственно поместили эти байты в память и сказали (с помощью приведения), что это именно функция.
    Я писал на Хабре об этом, можешь почитать комментарии, для меня они оказались полезны.
    http://habrahabr.ru/blogs/cpp/71234/

    ОтветитьУдалить
  3. Спасибо, прочитал комменты на Хабре. Многие пишут фразы "За такое нужно руки отрывать". По моему это все понты. Это же просто демонстрация, никто не говорит, что так нужно писать коммерческие продукты. Ты молодец, что пытаешься во всем разобраться.

    ОтветитьУдалить
  4. Спасибо! Конечно так делать не нужно, но это важно для понимания.

    ОтветитьУдалить

Можно использовать теги <b>, <i>