resueltos - memoria dinamica en c ejemplos
LinkedList-Cómo liberar la memoria asignada usando malloc (5)
Atraviesa la lista usando la misma lógica que arriba. Guarde el puntero curr-> next en algún lugar, libere la estructura curr y asigne curr con el cursor curr-> next puntero
Tengo un código C muy simple para construir una lista de Singly Linked como la siguiente, en la que asigno memoria para cada nodo dinámicamente utilizando malloc. Al final del código, quiero liberar la memoria para cada nodo asignado, me preguntaba cómo hacerlo: si comienzo desde el nodo principal primero y lo libero, los punteros a los nodos posteriores se pierden y se produce una fuga de memoria.
Otra forma es comenzar desde el nodo principal y seguir almacenando el puntero del nodo en una matriz separada de punteros o algo así, recorrer la lista hasta el puntero de cola mientras se almacenan los punteros del nodo, y una vez llegar al nodo de cola, almacenar eso también en la otra matriz de apunta y comienza a liberar de ese índice de matriz hacia atrás hasta que el nodo principal sea liberado.
¿Es esa la única forma de lograr lo que intento hacer?
En caso de que no quiera utilizar el segundo buffer, ¿cómo lo hago?
#include "stdio.h"
#include "stdlib.h"
struct lnk_lst
{
int val;
struct lnk_lst * next;
};
typedef struct lnk_lst item;
main()
{
item * curr, * head;
int i,desired_value;
head = NULL;
for(i=1;i<=10;i++)
{
curr = (item *)malloc(sizeof(item));
curr->val = i;
curr->next = head;
head = curr;
}
curr = head;
while(curr) {
printf("%d/n", curr->val);
curr = curr->next;
}
//How to free the memory for the nodes in this list?
for(i=1;i<=10;i++)
{
free()//?? What logic here
}
}
La forma habitual es con (pseudo-código primero):
node = head # start at the head.
while node != null: # traverse entire list.
temp = node # save node pointer.
node = node.next # advance to next.
free temp # free the saved one.
head = null # finally, mark as empty list.
La idea básica es recordar el nodo para liberar en una variable separada y luego avanzar al siguiente antes de liberarlo.
Solo necesita recordar un nodo a la vez, no toda la lista como propone.
En términos de lo que necesita agregar a su código, puede, durante la eliminación, usar head
como la head
la lista de actualización continua (como debe ser) y curr
para almacenar el elemento que está eliminando actualmente:
while ((curr = head) != NULL) { // set curr to head, stop if list empty.
head = head->next; // advance head to next element.
free (curr); // delete saved pointer.
}
Esto es un poco más corto que el pseudo-código anterior simplemente porque aprovecha la "taquigrafía" C para algunas operaciones.
Su código gratuito debe ser el siguiente:
lnk_lst temp = null;
while(head)
{
temp = head->next;
free(head);
head = temp;
}
También me gustaría agregar después de tu malloc, probablemente quieras verificar si la memoria fue asignada con éxito ... algo así como
if(curr)
Yo uso algo como esto:
for (p = curr; NULL != p; p = next) {
next = p->next;
free(p);
}
Contenido de Garbage Collector.h
#define Stack struct _stack
#define _MALLOC_S(type,num) (type *)_GC_malloc(sizeof(type)*num)
#pragma pack(1)
//Structure for adressing alocated memory into.
Stack {
int *adress_i;
char *adress_c;
float *adress_f;
double *adress_d;
Stack *next;
};
//Safe malloc
void *_GC_malloc(size_t size)
{
void* ptr = malloc(size);
if(ptr == NULL)
return _GC_malloc(size);
else
return ptr;
}
//Push new element on Stack after every malloc
void Add_New(int *i, float *f , double *d , char *c , Stack *p)
{
Stack *q = _MALLOC_S(Stack,1);
q->adress_i = i;
q->adress_f = f;
q->adress_c = c;
q->adress_d = d;
q->next = p->next;
p->next = q;
q = NULL;
}
//before ending program remove adresses that was allocated in memory, and pop entire Stack
void Free_All(Stack *p)
{
//free head (dummy element)
Stack *Temp = p->next;
Stack *_free = p;
free(_free);
void *oslobodi;
while(Temp != NULL)
{
_free = Temp;
Temp = _free->next;
if(_free->adress_i != NULL){
oslobodi = _free->adress_i;
free((int *)oslobodi);
}
else if(_free->adress_c != NULL){
oslobodi = _free->adress_c;
free((char *)oslobodi);
}
else if(_free->adress_f != NULL){
oslobodi = _free->adress_f;
free((float *)oslobodi);
}
else{
oslobodi = _free->adress_d;
free((double *)oslobodi);
}
free(_free);
}
_free = p = Temp;
}
/*
declare variable (var) and dinamicly alocate memory with simple macro,
and add to stack of linked list
*/
#define obj_int(var) int *var = _MALLOC_S(int,1); *var = 0; Add_New(var, NULL, NULL, NULL, Head);
#define obj_char(var) char *var = _MALLOC_S(char,1); *var = 0; Add_New(NULL, NULL, NULL, var, Head);
#define obj_float(var) float *var = _MALLOC_S(float,1); *var = 0; Add_New(NULL, var, NULL, NULL, Head);
#define obj_double(var) double *var = _MALLOC_S(double,1); *var = 0; Add_New(NULL, NULL, var, NULL, Head);
#define obj_struct(_type,_name) struct _type _*name = (struct _type *)malloc(sizeof(struct _type));
#define _INIT_ROW(var,num) for(int i = 0; i < num; i++) var[i] = 0;
/*
same, but for row!
*/
#define row_int(var, num) int *var = _MALLOC_S(int,num); _INIT_ROW(var,num) Add_New(var, NULL, NULL, NULL, Head);
#define row_char(var, num) char *var = _MALLOC_S(char,num); _INIT_ROW(var,num) Add_New(NULL, NULL, NULL, var, Head);
#define row_float(var, num) float *var = _MALLOC_S(float,num); _INIT_ROW(var,num) Add_New(NULL, var, NULL, NULL, Head);
#define row_double(var, num) double *var = _MALLOC_S(double,num); _INIT_ROW(var,num) Add_New(NULL, NULL, var, NULL, Head);
#define string(var, value) row_char(var, (strlen(value)+1)) strcpy(var, value);
/* with this you create a Stack and allocate dummy element */
#define Main(_type) _type main(void) { Stack *Head = _MALLOC_S(Stack,1); Head->next = NULL; Stack *_q_struct;
/* with this macro you call function for dealocate memory (garbage collecting)*/
#define End Free_All(Head); }
/*same thing for the other functions*/
#define Function(name_function, _type, ...) _type name_function(##__VA_ARGS__) { Stack *Head = _MALLOC_S(Stack,1); Head->next = NULL;
#define End_Ret(ret_var) Free_All(Head); return (ret_var); }
#define Call(name_function, ...) name_function(##__VA_ARGS__)
#define Define_Function(name_function, _type, ...) _type name_function(##__VA_ARGS__);
Ejemplo de some_program.c PS encabezado systemIO es un grupo de más encabezados como este arriba! :)
#include <systemIO.h>
Main(void)
int num_elements = 10;
row_int(row_elements, num_elements); //alocating row_elements object
for(int i = 0; i < num_elements; i++)
row_elements[i] = i; //initializing row_elements
End //Garbage delete row_elements and end of program
// row_int[0] = 0, row_int[1] = 1 ....