2011-01-02 3 views
2

Как я могу получить размер функции в C++?Как я могу получить размер функции C++?

Допустим, у меня есть функция:

void f() 
{ 
/*do something*/ 
} 

... Под «размером f», я имею в виду размер кода /*do something*/, начиная с адреса, указанного указателем на f.

+1

Вы имеете в виду длину или размер кода в памяти? – marcog

+6

Какой размер точно? Размер исходного кода C++ или размер машинного кода? В чем цель вообще? – Flinsch

+2

@ x1234x: вы хотите уточнить, что вы на самом деле хотите сделать * с этим ... Как было отмечено несколькими ответами, размер * в байтах * почти наверняка невозможно получить надежно, а для многих компиляторов, вероятно, бессмысленно даже если вы можете это определить - но, скорее всего, есть более простой и надежный способ получить то, что вы хотите без этого. – Shog9

ответ

4

Ну, технически я не верю, что вы можете, а не портативно.

Но практически вы вполне можете быть в состоянии сделать это:

void f() { ... } 
void g() { ... } 

char *fp = (char *)&f; 
char *gp = (char *)&g; 

int size = gp - fp; 

Вы вид, опираясь на компилятор поставить «г» после «F» в файле объекта, а также о том, что линкер с последующим костюм, поместив g после f.

Тогда вы просто вычитаете указатели, чтобы получить разницу.

Скорее всего, будут дополнены и другие возможные проблемы, поэтому это может быть не «точно» размер функции.

+5

Я был бы готов получить довольно случайные результаты с этим –

+0

Я не думаю, что есть что-то, препятствующее компоновщику отложить g до f, или очень далеко от f, тогда вы получаете мусор для размера. – AshleysBrain

+1

Yup, есть много места для этого, чтобы пойти совершенно неправильно, и я, конечно, не стал бы на него полагаться каким-либо переносным способом, но если это случится, чтобы работать на вашей платформе с вашим компилятором, то аллилуйя. –

11

Вы не можете. Это может быть даже не четкое понятие. Например, рассмотрим следующий код:

int f(int a) { 
    return (3*a)+1; 
} 

int g(int a) { 
    return (2*a)+1; 
} 

Я сомневаюсь, что это происходит на практике для этого конкретного примера, потому что это не будет оптимизация, но компилятор разрешается ввести блок кода, который вычисляет a+1 затем возвращает и переходит к этому блоку из каждой точки входа f и g (после выполнения умножения в каждом случае). Что тогда будет размером f? Должен ли он включать размер общего блока? Половина этого размера? В терминах C++ просто не имеет смысла утверждать, что функция f имеет размер.

Кроме того, «указатель на f» может быть не просто адресом функции f. Это, безусловно, дает возможность добраться до точки ввода f, но, например, на процессоре ARM в режиме межсетевого взаимодействия указатель на функцию, состоящую из кода Thumb, фактически является адресом первой команды плюс 1. В действительности, lsb указателя замаскирован CPU при выполнении перехода к функции, но этот бит сообщает CPU переключиться в режим Thumb, а не в режиме ARM. Таким образом, значение указателя не является адресом функции (хотя оно близко). Во всяком случае, точкой входа функции необязательно должно быть в начале ее - если ваш компилятор создает постоянные пулы или аналогичные, они могут предшествовать исполняемому коду.

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

1

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

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

1

Я предлагаю вам сделать что-то вроде strlen, кроме использования кода возврата вместо нуля в качестве терминатора.

+2

Функции могут иметь несколько операторов возврата. – SLaks

+1

Да, но они обычно скомпилированы как короткие прыжки, оставив функцию только с одной командой возврата. – Pyjong

+0

@stupid_idiot: Это будет зависеть от ABI. Некоторые ABI требуют, чтобы функция очищала свой собственный стек, другие требуют, чтобы вызывающий вызывал это. – greyfade

3

Большинство компиляторов имеют возможность вывода сборки. Сделайте это, найдите инструкции в документации вашего процессора и выполните математику.

0

Я хочу получить размер сгенерированного кода в байтах, чтобы я мог скопировать код в новое locatio и выполнить его оттуда. Я знаю, что это возможно, потому что я сделал это с помощью функции 2 и метода вычитания void f() {...} void g() {...}
char * fp = (char *) & f; char * gp = (char *) & g;
int size = gp - fp; , и он работал в визуальной студии в режиме выпуска. Причина, по которой я поставил этот вопрос, состоит в том, что у меня все еще есть проблемы с оптимизацией компилятора, и мне нужен более безопасный mothod.

+0

Пожалуйста, разместите это как комментарий к своему оригинальному сообщению или отредактируйте этот пост. – ybungalobill

+0

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

+0

Кроме того, вы хотите обсудить, как вы можете читать и писать исполняемый код. Флаги No-Execute могут серьезно нарушить такие подходы. – MSalters

-1

Функции не имеют «размера». Что касается C++, они не являются объектами, и они не занимают места для хранения. На практике, конечно, они существуют как инструкции исполнения в вашем исполняемом двоичном файле исполняемого файла.

Смежные вопросы