- Memoria dinámica y Valgrind
- ¿Qué significa assignment makes pointer from integer without a cast?
- ¿Qué significa implicit declaration of function 'una_funcion_interna'?
- ¿Cómo hago para que Valgrind me indique la línea en la que hay un error?
- ¿Qué significa Conditional jump or move depends on uninitialised value?
- ¿Qué significa Invalid read of size X / Invalid write of size X?
- Al ejecutar un programa dentro de Valgrind sucede algo distinto que sin él, ¿cómo puede ser?
Memoria dinámica y Valgrind
¿Qué significa assignment makes pointer from integer without a cast?
La siguiente operación es incorrecta:
int* valor = 4;
Ya que está asignando un valor entero a algo que es un puntero, y claramente es una dirección de memoria inválida.
Si lo que se quiere es tener un puntero a un entero, y que el valor del entero sea 4, existen estas dos alternativas:
int i = 4;
int* x = &i;
Esto funciona, pero hay que tener mucho cuidado, ya que la variable i se encuentra en el stack, por lo que la dirección de i sólo tiene sentido mientras la función actual no se termine. Al terminar la función actual pasa a ser una dirección de memoria inválida. Por otro lado:
int* x = malloc(sizeof(int));
if (!x) return false;
*x = 4;
En este caso, la dirección de memoria de x
es válida aún cuando termine la
función actual. Pero hay que tener cuidado de liberar ese espacio de memoria
cuando ya no sea necesario.
¿Qué significa implicit declaration of function 'una_funcion_interna'?
Las funciones que están definidas en un archivo .c
pero que no están
declaradas en el correspondiente archivo .h
no pueden ser llamadas fuera de
ese archivo .c
.
Sólo se puede llamar a funciones que están declaradas en el .h
, una función
interna del archivo .c
no debe ser llamada desde fuera de este archivo.
No se puede probar esas funciones directamente mediante las pruebas, sino que es
necesario probarlas indirectamente, mediante llamadas a las funciones que sí
están declaradas en el .h
.
¿Cómo hago para que Valgrind me indique la línea en la que hay un error?
Es necesario agregar la opción -g
(debug) a la línea de compilación. Eso le
dice al compilador que incluya la información de debugging en el binario, que
despues Valgrind usa para saber en qué línea están las instrucciones.
Además, la opción --track-origins=yes
sirve para llevar un registro del uso de
valores sin inicializar que pueden llegar a estar trayendo problemas.
¿Qué significa Conditional jump or move depends on uninitialised value?
Significa que una variable utilizada en algún salto condicional (por ejemplo,
if
) no está inicializada. Puede ser que se trate de una variable local que no
se asignó a nada, o de una variable que otra función debía guardar, y por algún
motivo no la guardó.
¿Qué significa Invalid read of size X / Invalid write of size X?
Este tipo de mensajes suele aparecer cuando se trata de leer o escribir más posiciones de las que fueron reservadar originalmente. Por ejemplo si se hizo:
void** datos = malloc(10 * sizeof(void*));
Despues se podrá leer y escribir hasta datos[9]
, al acceder a datos[10]
o
mayor, dará este error.
Al ejecutar un programa dentro de Valgrind sucede algo distinto que sin él, ¿cómo puede ser?
Puede pasar que dentro de Valgrind falle y fuera de este no, o al revés. Ambas situaciones son medianamente normales.
Esto se debe a que para poder verificar que no haya pérdidas de memoria, Valgrind maneja la memoria diferente que como se maneja normalmente. Es por eso que es algo más o menos común que cuando se ejecuta un programa con problemas dentro de Valgrind no se comporte exactamente igual que fuera de Valgrind.
Solucionando los problemas de memoria que tenga el programa se debería obtener el mismo comportamiento tanto dentro como fuera de Valgrind.