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.