Как получить длину функции в байтах? - PullRequest
16 голосов
/ 11 ноября 2010

Я хочу знать длину функции C (написанной мной) во время выполнения. Любой способ получить это? Кажется, sizeof здесь не работает.

Ответы [ 11 ]

17 голосов
/ 09 декабря 2012

Есть способ определить размер функции.Команда:

 nm -S <object_file_name>

Это вернет размеры каждой функции в объектном файле.Обратитесь к страницам руководства в GNU, используя 'man nm', чтобы собрать больше информации об этом.

14 голосов
/ 11 ноября 2010

В стандарте C нет способа получить объем памяти, занятый функцией.

13 голосов
/ 26 февраля 2014

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

mysec_start = .;
*(.mysection)
mysec_end = .;

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

#include <stdio.h>

int i;

 __attribute__((noinline, section(".mysection"))) void test_func (void)
{
    i++;
}

int main (void)
{
    extern unsigned char mysec_start[];
    extern unsigned char mysec_end[];

    printf ("Func len: %lu\n", mysec_end - mysec_start);
    test_func ();

    return 0;
}

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

4 голосов
/ 11 ноября 2010

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

Также обратите внимание, что макет функции также зависит от платформы, и есть некоторые вещи, которые делают термин «длина функции» неясным:

  1. Функции могут хранить используемые константы в разделах кода непосредственно после кода функции и получать к ним доступ, используя относительную к ПК адресацию (компиляторы ARM делают это).
  2. Функции могут иметь «прологи» и «эпилоги», которые могут быть общими для нескольких функций и, следовательно, лежать вне основного корпуса.
  3. Код функции может содержать другой код функции

Они все могут считать или не считать в длине функции.

Также функция может быть полностью встроена компилятором, поэтому она теряет свое тело.

3 голосов
/ 11 ноября 2010

Начало функции - указатель на функцию, вы уже это знаете.

Проблема в том, чтобы найти конец, но это можно сделать так:

#include <time.h>

int foo(void)
{
   int i = 0;
   ++i + time(0); // time(0) is to prevent optimizer from just doing: return 1;
   return i;
}

int main(int argc, char *argv[])
{
   return (int)((long)main - (long)foo);
}

Это работает здесь, потому что программа имеет ТОЛЬКО ДВЕ функции, поэтому, если код переупорядочен (основной реализован до foo), то вы получите несущественный (отрицательный) расчет, сообщающий, что он не работал таким образом, но это это сработало бы, если вы переместите код foo () в main () - просто вычтите размер main (), полученный с начальным отрицательным ответом.

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

Конечный (int) (long) приведен для переносимости между 32-битным и 64-битным кодом (указатели функций будут длиннее на 64-битной платформе).

Это очень портативный и должен работать достаточно хорошо.

3 голосов
/ 11 ноября 2010

Например, в Codewarrior вы можете разместить метки вокруг функции, например,

label1:
void someFunc()
{
    /* code goes here. */
}
label2:

, а затем вычислить размер как (int)(label2-label1), но это, очевидно, очень зависит от компилятора.В зависимости от вашей системы и компилятора может потребоваться взломать сценарии компоновщика и т. Д.

1 голос
/ 13 мая 2019

Я только что нашел решение для той же самой проблемы, но код, который я написал, зависит от платформы.

Идея заключается в том, чтобы поместить в конец функции известные коды операций и искать их с самого начала, считая пропущенные байты. Вот средняя ссылка, которую я объяснил с помощью некоторого кода https://medium.com/@gurhanpolat/calculate-c-function-size-x64-x86-c1f49921aa1a

1 голос
/ 16 августа 2016

Просто вычтите адрес вашей функции из адреса следующей функции.Но обратите внимание, что он может не работать в вашей системе, поэтому используйте его, только если вы уверены на 100%:

#include <stdint.h>

int function() {
    return 0;
}

int function_end() {
    return 0;
}

int main(void) {
    intptr_t size = (intptr_t) function_end - (intptr_t) function;
}
1 голос
/ 11 ноября 2010

В самом языке C не определено средство для возврата длины функции;просто задействовано слишком много переменных (компилятор, целевой набор команд, формат объектного файла / исполняемого файла, параметры оптимизации, параметры отладки и т. д.).Один и тот же исходный код может давать функции разных размеров для разных систем.

C просто не предоставляет никакой возможности отражения для поддержки такого рода информации (хотя отдельные компиляторы могут предоставлять расширения, такие как пример Codewarrior, цитируемый sskuce).Если вам нужно знать, сколько байт ваша функция занимает в памяти, вам придется напрямую проверить сгенерированный объект или исполняемый файл.

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

0 голосов
/ 19 марта 2014

Вы можете найти длину вашей функции C, вычитая адреса функций.Позвольте мне привести вам пример

int function1()
    {
    } 

int function2()
{
    int a,b;    //just defining some variable for increasing the memory size
    printf("This function would take more memory than earlier function i.e function01 ");
}

int main()
{
    printf("Printing the address of function01 %p\n",function01);
    printf("Printing the address of function02 %p\n",function02);
    printf("Printing the address of main %p\n",main);
    return 0;
}

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

Примечание. Обычно между одной функцией и другой существует разница в 16 байт.

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