2011-10-06 8 views
9

¿Hay alguna forma en gcc o clang (o cualquier otro compilador) de escupir información sobre si una estructura tiene agujeros (alineación de memoria)?Encontrar agujeros en las estructuras C debido a la alineación

Gracias.

ps: Si hay otra manera de hacerlo, por favor infórmeme.

+0

Se sabe que escribieron estructuras por lo que podría ser prácticamente seguro que lo hacen no contiene relleno. Si esto ayuda, avíseme y le informaré sobre los detalles. – Lindydancer

+0

Por curiosidad, ¿por qué? – detly

Respuesta

0

Puede explorar esta pregunta escribiendo código de sonda para un particular struct usando sizeof y &; si sizeof el nth miembro no es igual a la dirección del siguiente miembro menos la dirección de ese miembro, hay un agujero.

0

Puede detectar estos "agujeros" a través de la offsetof macro:

#include <stddef.h> 

struct test { 
    char a; 
    int b; 
}; 
... 
printf("%zu", offsetof(struct test, b)); 

Si se imprime más de 1, b obviamente tiene requisitos de alineación y el compilador produce un hueco en el medio.

Obviamente, esto ocurre en tiempo de ejecución, no en tiempo de compilación, pero puede escribir un script que produzca un archivo fuente similar, compilarlo y ejecutarlo antes del resto del proyecto y luego, en función del resultado, decisiones sobre cómo construir su proyecto.

No creo que ningún compilador tenga la capacidad de notificarte al respecto.

+0

¿Hay alguna manera de automatizar esto? – John

+0

Investigar las estructuras puede no ser suficiente, hay opciones de alineación, ya sea en el código o incluso en las CFLAGS. ¿De cuántas líneas de código estás hablando? ¿Es posible que las estructuras se utilicen para almacenar datos en archivos? –

+1

Mi pregunta es principalmente de naturaleza académica, pero me gustaría probar un par de millones de LOC. Los estucos son en su mayoría objetos CAD/CAE. – John

0

Una forma de encontrar tales agujeros sin analizar el código fuente y sin agregarle controles (usando offsetof() y similares) sería extraer la información de símbolo/depuración del objeto/archivo ejecutable/símbolo con alguna herramienta y observe las estructuras y los miembros definidos en ellos, sus desplazamientos y tamaños, y vea si todo se resume. Sin embargo, los sindicatos complicarán las cosas.

+0

Así que supongo que no hay un interruptor de compilación :). Sin embargo, es un tema interesante (para mí al menos). ¿Dónde comenzaría si quisiera analizar archivos de objetos? – John

+0

@John: primero vea si hay alguna herramienta que pueda leer la información del símbolo/depuración y deposítela en alguna forma legible por humanos. De lo contrario, vea qué herramientas, para las cuales tiene el código fuente, consuma esta información y desarrolle la suya en función de eso. Y, como de costumbre, consulte la documentación en los formatos de archivo. –

+0

esto es lo que 'pohole' et al do –

1

No sé cualquier herramienta automática, pero esto podría ser útil ejemplo:

#include <stddef.h> 

struct test { 
    typea a; 
    typeb b; 
    typec c; 
}; 

int gapB = offsetof(struct test, b) - (offsetof(struct test, a) + sizeof(typea)); 
int gapC = offsetof(struct test, c) - (offsetof(struct test, b) + sizeof(typeb)); 

printf("Gap of b:%d/n", gapB); 
printf("Gap of c:%d/n", gapC); 

* Nota: tendrá que hacerlo por cada dos miembros de su pegada.

1

de Gimpel FlexeLint/PC-lint puede hacer esto.

$ cat tst.c 
int main (void) 
{ 
    struct { 
     char c; 
     double d; 
     short s; 
    } f = { 1, 2.0, 3 }; 

    return f.c; 
} 

Se informará

$ flexelint -w1 +e95? tst.c 
FlexeLint for C/C++ (Unix) Vers. 9.00L, Copyright Gimpel Software 1985-2014 

--- Module: tst.c (C) 
       _ 
     double d; 
tst.c 5 Note 958: Padding of 7 byte(s) is required to align member on 8 byte 
    boundary 
    _ 
    } f = { 1, 2.0, 3 }; 
tst.c 7 Note 959: Nominal struct size (18 bytes) is not an even multiple of 
    the maximum member alignment (8 bytes) 
tst.c 7 Note 958: Padding of 6 byte(s) is required to align end of struct on 
    8 byte boundary 
0

Es necesario un programa de análisis que entiende la C/C++ e incluye estructuras necesarias incluye archivos.

Como respondió por @ Roee-gavirel, creo que la solución más fácil es crear un programa de prueba para imprimir los desplazamientos

técnicas
#include <stdio.h> 
#include <stddef.h> 

typedef struct tData { 
    long id;  /* 8 bytes */ 
    char name[8]; /* 8 bytes */ 
    float salary; /* 4 bytes */ 
} tData; 

tData d; 

int main() 
{ 
    size_t s_tData = sizeof(tData); 
    size_t s_id  = sizeof(d.id); 
    size_t s_name = sizeof(d.name); 
    size_t s_salary = sizeof(d.salary); 

    printf("sizeof(tData) = %zu\n\n", sizeof(d)); 

    printf("'id'  is at = %3zu occupies %zu bytes\n", 
     offsetof(tData, id), s_id); 
    printf("'name' is at = %3zu occupies %zu bytes\n", 
     offsetof(tData, name), s_name); 
    printf("'salary' is at = %3zu occupies %zu bytes\n", 
     offsetof(tData, salary), s_salary); 

    printf("\n"); 

    if (s_tData != s_id + s_name + s_salary) 
    printf("There is/are holes\n"); 

    return 0; 
} 
Cuestiones relacionadas