name keywords google etiquetas ejemplos c pointers memory-management malloc free

c - keywords - meta tags google



Memoria libre asignada en una funciĆ³n diferente? (3)

Cada vez que pasa un parámetro a una función, se realiza una copia y la función funciona en esa copia. Entonces, en su caso, está tratando de free una copia del objeto original, lo cual no tiene ningún sentido.

Debe modificar su función para tomar un puntero, y luego puede hacer que llame free directamente en ese puntero.

Intento aprender C y actualmente estoy tratando de escribir una estructura básica de pila de datos, pero parece que no puedo obtener malloc / free básico.

Aquí está el código que he estado usando (solo estoy publicando una pequeña parte aquí para ilustrar un problema específico, no el código total, pero el mensaje de error se generó simplemente al ejecutar este código de ejemplo en valgrind )

#include <stdio.h> #include <stdlib.h> typedef struct Entry { struct Entry *previous; int value; } Entry; void destroyEntry(Entry entry); int main(int argc, char *argv[]) { Entry* apple; apple = malloc(sizeof(Entry)); destroyEntry(*(apple)); return 0; } void destroyEntry(Entry entry) { Entry *entry_ptr = &entry; free(entry_ptr); return; }

Cuando lo ejecuto valgrind con --leak-check=full --track-origins=yes , me --leak-check=full --track-origins=yes el siguiente error:

==20674== Invalid free() / delete / delete[] / realloc() ==20674== at 0x4028E58: free (vg_replace_malloc.c:427) ==20674== by 0x80485B2: destroyEntry (testing.c:53) ==20674== by 0x8048477: main (testing.c:26) ==20674== Address 0xbecc0070 is on thread 1''s stack

Creo que este error significa que la función destroyEntry no tiene permiso para modificar la memoria asignada explícitamente en main. ¿Está bien? ¿Por qué no puedo free la memoria que asigné en main en otra función? (¿Y este comportamiento de alguna manera es específico de main?)


Esto está pasando por valor, lo que significa que se crea una copia, por lo tanto, intenta liberar la memoria, donde reside la entry variable local. Tenga en cuenta que la entry es un objeto con duración de almacenamiento automática y la memoria donde reside se liberará automáticamente cuando su programa se salga del alcance de la función destroyEntry .

void destroyEntry(Entry entry) { Entry *entry_ptr = &entry; free(entry_ptr); return; }

Su función debe tomar un puntero (pasar por referencia):

void destroyEntry(Entry *entry) { free(entry); }

Luego, en lugar de destroyEntry(*(apple)); simplemente llama a destroyEntry(apple); . Tenga en cuenta que si no hay otra funcionalidad conectada con la función destroyEntry , es redundante y es mejor simplemente llamar directamente a free(apple) .


Las otras respuestas aquí señalan el problema principal: porque usted desreferencia su manzana cuando llama a destroyEntry en main (), pasa por referencia, creando una copia.

Incluso una vez que conozca su problema, es útil volver al error e intentar conectar el texto de lo que está viendo con el problema, de modo que la próxima vez que lo haga sea más probable que lo resuelva rápidamente. Encuentro que los errores C y C ++ pueden parecer enloquecedoramente ambiguos a veces.

Generalmente, cuando tengo problemas para liberar punteros o eliminar objetos, me gusta imprimir las direcciones, especialmente cuando las asigno y justo cuando intento liberarlas. Valgrind ya te dio la dirección del puntero malo, pero ayuda a compararlo con uno bueno.

int main() { Entry * apple; apple = malloc(sizeof(Entry)); printf("apple''s address = %p", apple); // Prints the address of ''apple'' free(apple); // You know this will work }

Después de hacer eso, notará que la instrucción printf () le dio una dirección algo así como 0x8024712 (simplemente inventando una dirección en el rango general correcto), pero su salida valgrind dio 0x4028E58. Notarás que están en dos lugares muy diferentes (de hecho, "0x4 ..." está en la pila, no el montón de donde malloc () asigna, pero supongo que si estás comenzando eso no es una bandera roja para usted todavía), por lo que sabe que está tratando de liberar memoria del lugar equivocado, por lo tanto, "inválido libre ()".

Entonces, desde allí, puede decirse a sí mismo: "Está bien, de alguna manera mi puntero se está corrompiendo". Ya redujo su problema a un pequeño ejemplo compilable, por lo que no le tomará mucho tiempo resolverlo desde allí.

TL; DR: cuando se encuentre con errores relacionados con el puntero, intente imprimir las direcciones o encontrarlas en su depurador favorito. A menudo al menos te apunta en la dirección correcta.

Nada de esto es para desalentar la publicación de su pregunta en Stack Exchange, por supuesto. Cientos de programadores probablemente se beneficiarán de que lo hayas hecho.