2011-10-05 12 views
8

Estoy trabajando en un pequeño proyecto de hobby (www.github.com/AzP/GLSL-Validate) donde he tomado el código anterior (demasiada c y poca C++ para mi gusto, pero bueno, ¿qué puedo hacer? ¿lo haces?) y estoy tratando de ponerlo en funcionamiento en Linux y Windows. He tenido un par de bloqueos (corregidos ahora con suerte), pero desde que comencé a ejecutar Valgrind para encontrar los problemas, me atasqué con querer arreglar las quejas que recibo.Valgrind se queja con "Escritura inválida de tamaño 8"

Simplemente no puedo ver qué le pasa a este código (excepto que es bastante difícil de leer con buenos "números mágicos" repartidos por el lugar) con respecto a las quejas de Valgrind.

estoy corriendo Valgrind con el siguiente comando valgrind --track-origins=yes ./Program

291 // 
292 // Malloc a string of sufficient size and read a string into it. 
293 // 
294 # define MAX_SOURCE_STRINGS 5 
295 char** ReadFileData(char *fileName) 
296 { 
297  FILE *in = fopen(fileName, "r"); 
298  char *fdata; 
299  int count = 0; 
300  char**return_data=(char**)malloc(MAX_SOURCE_STRINGS+1); 
301 
302  //return_data[MAX_SOURCE_STRINGS]=NULL; 
303  if (!in) { 
304   printf("Error: unable to open input file: %s\n", fileName); 
305   return 0; 
306  } 
307 
308  // Count size of file by looping through it 
309  while (fgetc(in) != EOF) 
310   count++; 
311 
312  fseek(in, 0, SEEK_SET); 
313 
314 
315  if (!(fdata = (char *)malloc(count+2))) { 
316    printf("Error allocating memory\n"); 
317    return 0; 
318  } 
319  if (fread(fdata, sizeof(char), count, in) != count) { 
320    printf("Error reading input file: %s\n", fileName); 
321    return 0; 
322  } 
323  fdata[count] = '\0'; 
324  fclose(in); 
325  if(count==0){ 
326   return_data[0]=(char*)malloc(count+2); 
327   return_data[0][0]='\0'; 
328   OutputMultipleStrings=0; 
329   return return_data; 
330  } 
331 
332  int len = (int)(ceil)((float)count/(float)OutputMultipleStrings); 
333  int ptr_len=0,i=0; 
334  while(count>0){ 
335   return_data[i]=(char*)malloc(len+2); 
336   memcpy(return_data[i],fdata+ptr_len,len); 
337   return_data[i][len]='\0'; 
338   count-=(len); 
339   ptr_len+=(len); 
340   if(count<len){ 
341    if(count==0){ 
342    OutputMultipleStrings=(i+1); 
343    break; 
344    } 
345   len = count; 
346   } 
347   ++i; 
348  } 
349  return return_data; 
350 } 

Y aquí viene la salida Valgrind. ¿El is 0 bytes inside a block of size 6 alloc'd significa que puedo ignorarlo? Quiero decir '0 bytes' no suena peligroso? Pero desde que publiqué la pregunta aquí, creo que puedes ver que creo que debería prestarle atención.

==10570== Invalid write of size 8 
==10570== at 0x401602: ReadFileData(char*) (StandAlone.cpp:335) 
==10570== by 0x4013D8: CompileFile(char*, void*, int, TBuiltInResource const*) (StandAlone.cpp:255) 
==10570== by 0x401016: main (StandAlone.cpp:152) 
==10570== Address 0x5f627a0 is 0 bytes inside a block of size 6 alloc'd 
==10570== at 0x4C2880D: malloc (vg_replace_malloc.c:236) 
==10570== by 0x401475: ReadFileData(char*) (StandAlone.cpp:300) 
==10570== by 0x4013D8: CompileFile(char*, void*, int, TBuiltInResource const*) (StandAlone.cpp:255) 
==10570== by 0x401016: main (StandAlone.cpp:152) 
==10570== 
==10570== Invalid read of size 8 
==10570== at 0x401624: ReadFileData(char*) (StandAlone.cpp:336) 
==10570== by 0x4013D8: CompileFile(char*, void*, int, TBuiltInResource const*) (StandAlone.cpp:255) 
==10570== by 0x401016: main (StandAlone.cpp:152) 
==10570== Address 0x5f627a0 is 0 bytes inside a block of size 6 alloc'd 
==10570== at 0x4C2880D: malloc (vg_replace_malloc.c:236) 
==10570== by 0x401475: ReadFileData(char*) (StandAlone.cpp:300) 
==10570== by 0x4013D8: CompileFile(char*, void*, int, TBuiltInResource const*) (StandAlone.cpp:255) 
==10570== by 0x401016: main (StandAlone.cpp:152) 
==10570== 
==10570== Invalid read of size 8 
==10570== at 0x40163F: ReadFileData(char*) (StandAlone.cpp:337) 
==10570== by 0x4013D8: CompileFile(char*, void*, int, TBuiltInResource const*) (StandAlone.cpp:255) 
==10570== by 0x401016: main (StandAlone.cpp:152) 
==10570== Address 0x5f627a0 is 0 bytes inside a block of size 6 alloc'd 
==10570== at 0x4C2880D: malloc (vg_replace_malloc.c:236) 
==10570== by 0x401475: ReadFileData(char*) (StandAlone.cpp:300) 
==10570== by 0x4013D8: CompileFile(char*, void*, int, TBuiltInResource const*) (StandAlone.cpp:255) 
==10570== by 0x401016: main (StandAlone.cpp:152) 

EDIT: necesito el código para compilar en un compilador de C++, es por eso que tengo que seguir todos los elencos de malloc.

+0

Tal vez rastrear los valores de 'i' y ver si alguna vez superan 5. –

+0

¿Quiere decir 6, como en MAX_SOURCE_STRINGS + 1? – AzP

Respuesta

13

Esto se ve mal:

char**return_data=(char**)malloc(MAX_SOURCE_STRINGS+1); 

probablemente debería ser:

char **return_data = malloc ((MAX_SOURCE_STRINGS+1) * sizeof *return_data); 

(espacios añade por conveniencia).

EDITAR: Un poco de explicación adicional: Cuando dice return_data[i]=... usted está tratando de escribir algo en return_data[i]. Ahora, return_data es char**, entonces return_data[i] es char*. Entonces estás escribiendo un puntero en algún lugar en la memoria.

Parece que sus punteros tienen 8 bytes de longitud (lo que está bien), pero solo ha asignado 6 bytes: MAX_SOURCE_STRING+1. Entonces hay un problema

El hecho de que intente escribirlo en offset 0 no importa; todavía está tratando de escribir más datos de los que puede tomar el búfer, y de eso es de lo que se queja Valgrind.

Para resolver el problema, debe asignar suficiente espacio para contener una serie de punteros. Cada puntero toma sizeof(char*), que también se puede escribir como sizeof(*return_data) o sizeof *return_data. Entonces, en total debe asignar n * sizeof *return_data bytes, donde n es (en su caso) el número mágico 6.

+0

¡Gracias por su respuesta! Lo interpreté como return_data es una matriz de char *, que también se puede considerar como una matriz de matrices de caracteres. Pensé que el malloc asignaría una matriz de 6 matrices de caracteres. Luego, el código realiza otro malloc en la línea 335, donde asigna el subarreglo en la posición i (return_data [i]). Así que podríamos llegar a esa matriz haciendo, por ejemplo, return_data [i] [0] etc. – AzP

+0

Pero al igual que usted dijo, cambiar el MALLOC_SOURCE_STRINGS a 8 en realidad se deshace de la queja.Tengo que volver a pensar esto hasta que entienda lo que estoy haciendo mal, y si coincide con su información =) – AzP

+0

Ah, creo que lo entiendo ahora. Tiene razón en cuanto a los punteros, pensé que necesitábamos 6 punteros, y que ocuparon 1 byte cada uno, lo que por supuesto no es el caso. – AzP

Cuestiones relacionadas