[C con Clase] Que problemas puede causar memcpy al introducir un buffer de datos en un struct

José Luis Torre joseluistorrehernandez en gmail.com
Vie Oct 26 22:20:02 CEST 2012


Hola Marta:

Te envío algunas ideas, en código, para ver si puedes utilizarlas.

// tamaño suficiente para almacenar los datos de la máxima estructura
#define N 10000

void leer_fichero_datos(const char nombre[], char mem[]) {
     FILE *f;

     f = fopen(nombre, "r");

     // leer los datos sobre una memoria

     fclose(f);
}

char memoria[N];

void iniciar_a_ceros(void) {
     int i;
     for (i = 0; i < N; ++i)
     {
         memoria[i] = \x00 ;
     }

}


void test_jose_luis(void) {

     // si la memoria es toda de 0
     iniciar_a_ceros();
     memcpy(&mod_highest_comp_data_inst_state, memoria,8);

     // si la memoria tiene datos

     // abrir fichero de datos

     // leer el número de objetos

     for (int i = 0; i < num_objetos; ++i) {

         // leer el nombre de la estructura

         // leer el tamaño de la estructura; dim

         // leer el contenido de la estructura

         // asignar los datos leidos a la estructura,
         // posiblemente seleccionada mediante un switch

         memcpy(estructura, contenido, dim);

     }

     // cerrar el fichero de datos
}


Saludos
José Luis

El 25 de octubre de 2012 10:01, marta vic <marvicekl en gmail.com> escribió:

> Yo tengo un programa en c que se ejecuta con KLEE
> KLEE lo que hace es de forma automatica obtener casos de prueba,
> Te adjunto un ejemplo sencillo, y este ejemplo mas complejo para que veas
> como puede variar
>
> Muchas gracias por la ayuda, la verdad que al principio me costo incluso
> encontrar esta solucion y cuando la encontre decidi que me quedaba con esto.
> Pero si tienes una idea mejor me vendria genial.
>
> Un saludo
> Marta
> ___________________________________________________________________________
>
> *1 Este es el ejemplo de un fichero de datosde klee*
>  en realidad producira muchos ficheros como este (en concreto creo que los
> datos de este caso no se corresponen exacatamente con los que te muestro
> luego, si son las mismas estructuras, pero creo que no corresponde el valor
> que introduzco luego.
>
>
>
> ktest file : 'klee-last/test000005.ktest'
> args       : ['wrapper_syncs.o']
> num objects: 5
> object    0: name: 'selection'
> object    0: size: 4
> object    0: data: 1
> object    1: name: 'state_8'
> object    1: size: 4
> object    1: data: 0
> object    2: name: 'state_20'
> object    2: size: 484
> object    2: data:
> '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
> object    3: name: 'state_24'
> object    3: size: 8
> object    3: data: '\x00\x00\x00\x00\x00\x00\x00\x00'
> object    4: name: 'state_28'
> object    4: size: 28
> object    4: data:
> '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
>
>
>
> _____________________________________________
>
> Un ejemplo de como lo intrudiciria seria:
> (aunque no se corresponden los datos con los del ejemplo anterior, si se
> corresponden las estructuras)
>
> *2 Las estructuras en este caso serian: en el mismo orden que se
> introducen posteriormente*
>
> typedef struct {int pos_offset;} MyModule_tc3_controller_state_t;
>
> typedef struct {int drivemode;
> int speed_arr[20];
> int steering_arr[10][10];} MyModule_guidance_state_t;
>
> typedef struct {int dir;
> int angle;} MyModule_panning_controller_state_t;
>
> typedef struct {int state;
> int counter;
> int angle;
> signed int edge_start_angle;
> signed int edge_end_angle;
> signed int distance;
> signed int heading;}
>
> ________________________________
>
> *3 INTRODUCCION DE LOS DATOS: Como se puede ver arriba, klee va a
> producir la info del tamaño de la estructura y yo voy a saber a que
> estructura se corresponde.*
> *
> *
>  value_state = 0;
> memcpy(&MyModule_autonomous_car_tc3_cntrl_inst_state,&value_state,4);
>  memcpy(&
>
> MyModule_guidance_system_g_inst_state,"\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",484);
>
> memcpy(&MyModule_targeting_system_pc_inst_state,"\x00\x00\x00\x00\x00\x00\x00\x00",8);
>
> memcpy(&MyModule_targeting_system_bd_inst_state,"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",28);
>
>
> El 25 de octubre de 2012 00:06, José Luis Torre <
> joseluistorrehernandez en gmail.com> escribió:
>
> Marta:
>>
>> Muéstrame un ejemplo de la salida del programa KLEE y te comentaré cómo
>> puedes leerlo desde tu programa.
>>
>> Saludos
>> José Luis
>>
>>
>> El 24 de octubre de 2012 22:26, marta vic <marvicekl en gmail.com> escribió:
>>
>> Muchisimas gracias por las respuestas
>>>
>>> La cuestion es que yo recibo ese valor de otro programa y lo tengo que
>>> introducir en un programa c para inicializar la estructura,
>>> el programa (KLEE) me da directamente esa informacion y la estructura
>>> siempre sera la adecuada, pro qeu es la misma estructura que klee ha
>>> analizado y me ha dado ese valor hexadecimal.
>>>
>>> por lo tanto necesito una forma de re introducir el valor en la
>>> estructura y no creo que con memset pueda hacerlo (aunque voy a mirar si
>>> tengo alguna alternativa)
>>>
>>> Los valores de la salida seran distintos a 0, ya que lo que hace klee es
>>> generar valores para las estructuras pero no es capaz de separarlos por
>>> campos de ahi el problema
>>>
>>> muchisimas gracias
>>> mirare la documentacion  que me aconsejas
>>>
>>> Un saludo
>>> El 8 de octubre de 2012 12:03, Salvador Pozo <salvador en conclase.net>escribió:
>>>
>>> El pasado 2012-10-07 22:10:00, marta vic escribió:
>>>>
>>>> mv> Hola
>>>> mv> Tengo una duda, y busco mas lugares donde pueda acceder a
>>>> explicaciones o
>>>> mv> documentacion que una explicacion concreta,
>>>> mv> me gustaria definir los problemas que se pueden encontrar al
>>>> intentar
>>>> mv> ejecutar un codigo como este:
>>>> mv> memcpy(&estructura1,"\x00\x00\x00\x00\x00\x00\x00\x00",8);
>>>> mv> en este caso
>>>> mv> estructura1{
>>>> mv>     int a;
>>>> mv>     int b;
>>>> mv> }
>>>>
>>>> Hola:
>>>>
>>>> Antes de ver qué problemas puede haber en este mecanismo, comentar que
>>>> existen soluciones mejores para hacer lo que se pretende.
>>>>
>>>> En la misma biblioteca que memcpy existe otra función, memset, que está
>>>> diseñada específicamente para esa tarea.
>>>>
>>>> En tu caso concreto, podría usarse de este modo:
>>>>
>>>> ----8<------
>>>> struct {
>>>>     int a;
>>>>     int b;
>>>> } estructura1;
>>>>
>>>> memset(&estructura1,0,sizeof(structura1));
>>>> ----8<------
>>>>
>>>> Esto tiene algunas ventajas evidentes:
>>>> 1) No necesitas una cadena de ceros de longitud arbitraria, ya que
>>>> usamos un único valor de tipo int, que se usará como un byte (un unsigned
>>>> char).
>>>> 2) No tenemos que usar una constante como tamaño de la estructura, en
>>>> su lugar usamos en operador sizeof, que nos da el tamaño exacto de la
>>>> estructura, independientemente de la arquitectura y de la alineación de
>>>> bytes usada.
>>>>
>>>> Respondiendo a tu pregunta, ahora no puedo decirte un lugar donde
>>>> puedas encontrar información sobre ese tema, sobre todo, porque no sé si
>>>> existe algo tan concreto.
>>>>
>>>> Los problemas son, entre otros, los que ha indicado José Luis:
>>>>
>>>> - Dependiendo de la plataforma y del compilador, los valores enteros
>>>> pueden tener distintos tamaños. En general, el tamaño de una estructura
>>>> estará determinado por el tamaño de cada uno de sus componentes, y en C ese
>>>> tamaño no está definido, salvo que el de int es mayor o igual que char, y
>>>> el de long int mayor o igual que int. (
>>>> http://c.conclase.net/curso/index.php?cap=002#inicio)
>>>>
>>>> - Otro problema es el de alineación de las variables en memoria. A
>>>> menudo, para mejorar la eficacia de los procesadores a la hora de acceder a
>>>> memoria, las direcciones de las variables pueden ser múltiplos de 2, de 4 o
>>>> de 8, dependiendo del tamaño de la palabra del microprocesador.
>>>> (http://c.conclase.net/curso/index.php?cap=011b#inicio)
>>>>
>>>> Por ejemplo, en esta estructura:
>>>> struct A {
>>>>    int x;
>>>>    char a;
>>>>    int y;
>>>>    char b;
>>>> };
>>>>
>>>> Si el alineamiento es de cuatro bytes, las posiciones de memoria de
>>>> cada elemento del array no serán consecutivas:
>>>> 0-3: x
>>>> 4: a
>>>> 5-7: libre
>>>> 8-11: y
>>>> 12: b
>>>> 13-15: libre
>>>>
>>>> De este modo, una estructura que debería ocupar 10 bytes, en realidad
>>>> ocupa 16.
>>>>
>>>> Es más, el tamaño final puede depender del orden en que se declaran los
>>>> elementos de la estructura, y de si se activa o no el alineamiento de bytes.
>>>>
>>>> - El problema con el formato Big Endian o Little Endian, en el caso
>>>> concreto de inicializar con ceros, no tiene importancia. Otro tema sería si
>>>> los valores iniciales no fueran nulos.
>>>>
>>>> - Por último, los problemas son casi iguales si se trata de arrays o
>>>> estructuras. En los dos casos nos afecta la arquitectura y el problema del
>>>> alineamiento de bytes.
>>>>
>>>> En cuanto a soluciones, arriba te he comentado la que se suele usar en
>>>> C, que consiste en utilizar la función memset.
>>>>
>>>> En C++ es preferible usar constructores, al menos en el caso de
>>>> estructuras, ya que para los arrays puede interesar más usar memset también.
>>>>
>>>> En general, no es buena idea que el programador haga las cuentas si
>>>> puede hacer que las haga el compilador. Para hacer las cuentas a mano, como
>>>> en tu ejemplo, debemos asumir el tamaño de las variables y cierta
>>>> alineación, pero eso hace que el programa no sea transportable, y no
>>>> podemos garantizar que funcione correctamente si se compila en otra
>>>> plataforma, con otro sistema operativo o con otro compilador.
>>>>
>>>> Seguramente encuentres documentación en la red haciendo consultas con:
>>>> memcpy gibendian
>>>> memcpy alineamiento bytes
>>>> memcpy plataformas
>>>>
>>>> Suerte, y hasta pronto.
>>>>
>>>> --
>>>> Salvador Pozo (Administrador)
>>>> mailto:salvador en conclase.net
>>>> _______________________________________________
>>>> Lista de correo Cconclase Cconclase en listas.conclase.net
>>>>
>>>> http://listas.conclase.net/mailman/listinfo/cconclase_listas.conclase.net
>>>> Bajas: http://listas.conclase.net/index.php?gid=2&mnu=FAQ
>>>>
>>>
>>>
>>> _______________________________________________
>>> Lista de correo Cconclase Cconclase en listas.conclase.net
>>> http://listas.conclase.net/mailman/listinfo/cconclase_listas.conclase.net
>>> Bajas: http://listas.conclase.net/index.php?gid=2&mnu=FAQ
>>>
>>
>>
>>
>> --
>> José Luis Torre
>> ww.ehu.es
>>
>>
>>
>> _______________________________________________
>> Lista de correo Cconclase Cconclase en listas.conclase.net
>> http://listas.conclase.net/mailman/listinfo/cconclase_listas.conclase.net
>> Bajas: http://listas.conclase.net/index.php?gid=2&mnu=FAQ
>>
>
>
> _______________________________________________
> Lista de correo Cconclase Cconclase en listas.conclase.net
> http://listas.conclase.net/mailman/listinfo/cconclase_listas.conclase.net
> Bajas: http://listas.conclase.net/index.php?gid=2&mnu=FAQ
>



-- 
José Luis Torre
ww.ehu.es
------------ próxima parte ------------
Se ha borrado un adjunto en formato HTML...
URL: <http://listas.conclase.net/pipermail/cconclase_listas.conclase.net/attachments/20121026/5bee308f/attachment.html>


Más información sobre la lista de distribución Cconclase