Найти размер функции в C

Я изучаю указатели функций, я понимаю, что мы можем указывать на функции, используя указатели функций. Затем я предполагаю, что они остаются в памяти. Они остаются в стеке или куче? Можем ли мы рассчитать их размер?

7 ответов

Решение

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

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

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

int first_function()
{
   ...
}

void second_function( int arg )
{
    ...
}

int main( void )
{
    int first_function_length = (int)second_function - (int)first_function ;
    int second_function_length = (int)main - (int)second_function ;

}

Однако YMMV; Я попробовал это в VC++, и он дал только действительные результаты в сборке "Release"; результаты для отладочной сборки не имели никакого реального смысла. Я полагаю, что это упражнение только для интереса и не имеет практического применения.

Конечно, другой способ наблюдать за размером вашего кода - это посмотреть на разборку кода в вашем отладчике.

Они (обычно) отделены от стека или кучи.

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

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

Есть интересный способ узнать размер функции.

#define RETN_empty 0xc3
#define RETN_var   0xc2  
typedef unsigned char BYTE;
size_t FunctionSize(void* Func_addr) {
    BYTE* Addr = (BYTE*)Func_addr;
    size_t function_sz = 0;
    size_t instructions_qt = 0;
        while(*Addr != (BYTE)RETN_empty && *Addr != (BYTE)RETN_var) {
            size_t inst_sz = InstructionLength((BYTE*)Addr);
            function_sz += inst_sz;
            Addr += inst_sz;
            ++instructions_qt;
        }
    return function_sz + 1;
}

Но вам нужна функция, возвращающая размер инструкции. Вы можете найти функцию, которая определяет длину инструкции здесь: Получить размер инструкций по сборке. Эта функция в основном продолжает проверять инструкции функции до тех пор, пока не найдет инструкцию для возврата (RETN)[ 0xc3, 0xc2], и не вернет размер функции.

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

Ядро linux использует это для профилирования во время выполнения.

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

Вы действительно должны знать его размер во время выполнения? Если нет, вы можете получить это простым objdump -t -i .text a.out где a.out - имя вашего двоичного файла. .text где компоновщик помещает код, и загрузчик может сделать эту память доступной только для чтения (или даже только для выполнения). Если да, как было сказано в предыдущих постах, есть способы сделать это, но это сложно и непереносимо... Клиффорд дал самое простое решение, но компоновщик редко помещает функцию таким последовательным образом в финал двоичный файл. Другим решением является определение разделов в вашем скрипте компоновщика с помощью прагм и резервирование хранилища для глобальной переменной, которая будет заполнена компоновщиком разделом SIZEOF(...), содержащим вашу функцию. Это зависит от линкера, и не все линкеры предоставляют эту функцию.

Если есть что-то похожее на размер функции, то это должен быть размер STACK FRAME. Или еще лучше, пожалуйста, постарайтесь понять, какой именно, по вашему мнению, должен быть размер функции? Вы имеете в виду его статический размер, то есть размер всего его кода операции, когда он загружается в память? Если это то, что вы имеете в виду, то я не вижу, чтобы это была какая-либо функция, предоставляемая языком, чтобы выяснить это. взломать. Там может быть много. Но я не пробовал это.

С не имеет сборщика мусора. Наличие указателя на что-то не заставляет его оставаться в памяти.

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

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

#include<stdio.h>

int main(){
    void demo();
    int demo2();
    void (*fun)();
    fun = demo;
    fun();
    printf("\n%lu", sizeof(demo));
    printf("\n%lu", sizeof(*fun));
    printf("\n%lu", sizeof(fun));
    printf("\n%lu", sizeof(demo2));
    return 0;
}

void demo(){
    printf("tired");    
}

int demo2(){
    printf("int type funciton\n");
    return 1;
}

надеюсь, вы получите ответ, все функции где-то хранятся

Здесь вывод кода

вывод кода выше

Другие вопросы по тегам