2011-06-14 8 views
9

Así que me he estado enseñando a mí mismo C, y con la esperanza de aprender a administrar la memoria correctamente desde el principio y escribir mejor código, he estado ejecutando Valgrind en todo. Esto me ha ayudado con fugas de memoria, pero parece que no puedo deshacerme de esto. "El salto o movimiento condicional depende de los valores no inicializados/El valor no inicializado fue creado por una situación de asignación de montón", aunque lo he reducido a este bloque de código:¿Podría valgrind queja sobre valores no inicializados ser un falso positivo?

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 

int main()  
{ 
    char* test = (char*) malloc(3); 
    strncpy(test, "123", 2); 
    printf("%s\n", test); 
    free(test); 
    return 0; 
} 

Cuando corro con Valgrind ---track-origins=yes, consigo esta salida:

==91702== Conditional jump or move depends on uninitialised value(s) 
==91702== at 0x100011507: strlen (mc_replace_strmem.c:282) 
==91702== by 0x1000AA338: puts (in /usr/lib/libSystem.B.dylib) 
==91702== by 0x100000EFA: main (valgrind_test.c:10) 
==91702== Uninitialised value was created by a heap allocation 
==91702== at 0x100010345: malloc (vg_replace_malloc.c:236) 
==91702== by 0x100000EEA: main (valgrind_test.c:8) 

este parece ser un falso positivo para mí, pero no soy lo suficientemente seguro de mi poseer el conocimiento para escribirlo como tal. Tal vez estoy asignando mal o usando strncpy mal? No estoy seguro.

Gracias de antemano

+4

Su cadena no tiene terminador, por lo que valgrind probablemente tenga razón cuando se queja. –

+1

Usando snprintf aquí sería mejor en mi humilde opinión. snprintf (prueba, 3, "123"); – puffadder

Respuesta

17

No, esto es código.

Tiene un bloque de memoria con 3 caracteres no inicializados. Luego copie "12" en él y no finalice. Tenga cuidado con strncpy().

cito the documentation:

La función strncpy() es similar, excepto que no se copian más de n bytes de src. Por lo tanto, si no hay un byte nulo entre los primeros n bytes de src, el resultado no terminará en nulo.

Como no hay terminación dentro de los primeros 2 caracteres de la fuente, el destino no finaliza.

+3

Nunca duele agregar una nota: ** nunca use 'strncpy' ** –

+0

Parece que no leí la página del manual lo suficientemente cerca, pensé que strncpy llenaría el resto de la cadena objetivo con nulos. Eso solo sucede cuando n es más largo que la cadena fuente. – pivotal

+0

@R .. 'strncpy' es útil para formatos de registro de tamaño fijo. – ninjalj

1

Su cadena no tiene terminador, por lo que valgrind probablemente tenga razón cuando se queje. Cambio:

strncpy(test, "123", 2); 

a:

strcpy(test, "12"); 
4

formas idiomáticas utilizar strcpy() y strncpy():

Si sabe que el tampón tiene espacio para la cadena más el terminador NULL, puede utilizar strcpy() . Esto probablemente usará constantes, o tendrá controles en el código (debe asegurarse de que los controles sean correctos).

De lo contrario, puede hacerlo:

strncpy(dest, src, length); 
dest[length - 1] = '\0'; 

que tiene las siguientes desventajas:

  • puede truncar cadenas.
  • es potencialmente ineficiente, ya que siempre llena length bytes.

También está OpenBSD's strlcpy().

Cualquier otro uso de strcpy()/strncpy() es potencialmente sospechoso, y debe consultarlo detenidamente.

En pocas palabras: evite las funciones de cadena C para cualquier cosa moderadamente compleja, intente utilizar alguna biblioteca para cadenas dinámicamente asignadas. Qmail/Postfix lanzan sus propios, GNU tiene obstacks.

Cuestiones relacionadas