2010-11-11 17 views
12

Quiero saber la duración de la función C (escrita por mí) en tiempo de ejecución. ¿Algún método para obtenerlo? Parece que sizeof no funciona aquí.¿Cómo obtener la longitud de una función en bytes?

+2

Por favor, defina "longitud de función C" ** ** precisamente – pmg

+0

me refiero a la memoria ocupada por el código de esta función. – Thomson

+1

Si me lo está preguntando por la misma razón que me pregunté hace muchos años, permítanme señalar [Escribir un nuevo Jit] (http://stackoverflow.com/questions/4097301/writing-a-new-jit) –

Respuesta

13

En la norma C no hay forma de obtener la cantidad de memoria ocupada por una función.

0

No existe una forma estándar de hacerlo ni en C ni en C++. Es posible que existan modos de implementación específicos para la plataforma/implementación, pero no conozco ningún

3

En ej. Codewarrior, puedes colocar etiquetas alrededor de una función, p.

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

y luego calcular el tamaño como (int)(label2-label1), pero esto es obviamente muy compilador dependiente. Dependiendo de su sistema y compilador, puede tener que piratear scripts de enlazador, etc.

+0

No lo sabía. Gracioso. Más o menos – haylem

+2

Hay una [extensión GCC] similar (http://gcc.gnu.org/onlinedocs/gcc-4.5.0/gcc/Labels-as-Values.html#Labels-as-Values), usándola estarías capaz de calcular el tamaño como '&& label2 - && label1' – Hasturkun

+0

Espero que esto funcione, pero parece que no puede funcionar en Visual C++ (lenguaje C). – Thomson

4

Los ejecutables (al menos los que tienen información de depuración eliminada) no almacenan longitudes de función de ninguna manera. Entonces no hay posibilidad de analizar esta información en tiempo de ejecución por sí mismo. Si tiene que manipular las funciones, debe hacer algo con sus objetos en la fase de vinculación o accediendo a ellos como archivos desde su ejecutable. Por ejemplo, puede decirle al vinculador que vincule las tablas de símbolos como una sección de datos ordinarios en el ejecutable, asígneles un nombre y analice cuando se ejecuta el programa. Pero recuerde, esto sería específico para su enlazador y formato de objeto.

También tenga en cuenta, que la disposición función es también la plataforma específica y hay algunas cosas que hacen que el término "longitud de la función" claro:

  1. funciones pueden tener tienda utilizado constantes en secciones de código directamente después del código de función y el acceso usando el direccionamiento relativo de PC (los compiladores ARM hacen esto).
  2. Las funciones pueden tener "prólogos" y "epilogs" que pueden ser comunes a varias funciones y, por lo tanto, se encuentran fuera del cuerpo principal.
  3. del código de función inline otro código de función

Todos ellos pueden contar o no contar en función longitud.

También la función puede estar completamente enlistada por el compilador, por lo que pierde su cuerpo.

+0

pueden pero estas funciones aún tienen longitud fija, simplemente se comportarán mal sin esas dependencias externas. Estas funciones se pueden reconstruir para que sean autónomas tomando sus dependencias como argumentos, y muchas funciones, especialmente las funciones de devolución de llamada, son exactamente ésas. – Dmitry

1

No hay ninguna facilidad definida dentro del lenguaje C para devolver la longitud de una función; simplemente hay demasiadas variables involucradas (compilador, conjunto de instrucciones de destino, archivo de objeto/formato de archivo ejecutable, configuración de optimización, configuración de depuración, etc.). El mismo código fuente puede dar como resultado funciones de diferentes tamaños para diferentes sistemas.

C simplemente no proporciona ningún tipo de capacidad de reflexión para admitir este tipo de información (aunque los compiladores individuales pueden suministrar extensiones, como el ejemplo Codewarrior citado por sskuce). Si necesita saber cuántos bytes ocupa su función en la memoria, tendrá que examinar el objeto generado o el archivo ejecutable directamente.

sizeof func no funcionará porque la expresión func se trata como un puntero a la función, por lo que obtendrá el tamaño de un valor de puntero, no la función en sí.

+0

En un compilador conforme, 'sizeof func' no funciona porque un designador de función no es un operando válido del operador' sizeof'. – caf

+0

@caf: * facepalm * Sí, tienes razón. Lo sabía. De Verdad. –

+0

@JohnBode mientras tenga razón en que esta información no es portátil; el compilador todavía es consciente de todos estos factores en tiempo de compilación, y el resultado tiene perfecto sentido para esa plataforma en particular. Conocer el tamaño de una función es significativo en esa plataforma, ya que le permite memcpy el shellcode de funciones de "solo lectura", que tiene implicaciones muy interesantes y constantes que no podemos estudiar sin tener esa característica. – Dmitry

3

El inicio de la función es el puntero a la función, eso ya lo sabe.

El problema es encontrar al final, pero eso se puede hacer de esta manera:

#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); 
} 

Se trabaja aquí porque el programa sólo tiene dos funciones por lo que si se vuelve a pedir el código (principal implementado antes de foo) entonces obtendrás un cálculo irrelevante (negativo), haciéndote saber que no funcionó de esta manera, pero que funcionaría si movieras el código foo() a main() - solo restas el tamaño principal() que obtuviste la respuesta negativa inicial.

Si el resultado es positivo, entonces será correcto, si no se realiza el relleno (sí, algunos compiladores inflan el código felizmente, ya sea por alineación o por otras razones menos obvias).

La conversión final (int) (larga) es para la portabilidad entre códigos de 32 bits y de 64 bits (los punteros a las funciones serán más largos en una plataforma de 64 bits).

Esto es fácil de transportar y debería funcionar razonablemente bien.

12

Hay una manera de determinar el tamaño de una función. El comando es:

nm -S <object_file_name> 

Esto devolverá los tamaños de cada función dentro del archivo del objeto. Consulte las páginas del manual en GNU usando 'man nm' para reunir más información al respecto.

+0

u objdump, FWIW. – sehe

+0

'nm -S --size-sort -t d | grep 'muestra el tamaño en la base 10 (' -t d' para * decimal *) de símbolos que contienen 'patrón' en su nombre, ordenados por tamaño. Muy genial. – hdl

12

Puede obtener esta información del vinculador si está utilizando un script de enlazador personalizado. Añadir una sección enlazador sólo para la función dada, con símbolos de engarce a cada lado:

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

A continuación, puede asignar la función específicamente a esa sección. La diferencia entre los símbolos es la longitud de la función:

#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; 
} 

Este ejemplo es para GCC, pero cualquier cadena de herramientas C debe tener una forma de especificar qué sección para asignar una función a. Verificaría los resultados contra la lista del ensamblado para verificar que esté funcionando de la manera que desea.

+0

Puede hacer esto sin un script de enlazador personalizado llamando a la sección por un nombre de identificador C válido, por ejemplo 'mysection' en lugar de' .mysection', y usando '__start_mysection' y' __stop_mysection' en lugar de 'mysec_start' y' mysec_end '. El vinculador define automáticamente estos símbolos para cada sección encontrada. – Janiels

-3

Puede encontrar la longitud de su función C restando las direcciones de las funciones. Déjenme dar un ejemplo

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; 
} 

Espero que se obtendría su respuesta después de la compilación. Después de la compilación, podrá ver la diferencia de tamaño de function01 y function2.

Nota: Normalmente hay 16bytes de diferencia entre una función y otra.

+0

su ejemplo no está probando nada :) ¡solo está imprimiendo direcciones de funciones! –

1

Simplemente reste la dirección de su función de la dirección de la siguiente función. Pero tenga en cuenta que puede que no funcione en su sistema, a fin de utilizarlo sólo si está 100% seguro:

#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; 
} 
Cuestiones relacionadas