C-estructuras liberadoras


Digamos que tengo esta estructura

typedef struct person{
    char firstName[100], surName[51]
} PERSON;

Y estoy asignando espacio por malloc y llenándolo con algunos valores

PERSON *testPerson = (PERSON*) malloc(sizeof(PERSON));
strcpy(testPerson->firstName, "Jack");
strcpy(testPerson->surName, "Daniels");

¿Cuál es la forma correcta y segura de liberar toda la memoria tomada por esa estructura? ¿Es suficiente" free(testPerson); " o necesito liberar el atributo de cada estructura uno por uno?

Esto me lleva a otra pregunta - ¿cómo se almacenan las estructuras en la memoria? Noté un comportamiento extraño-cuando intento imprimir la dirección de la estructura es igual a su primer atributo dirección.

printf("Structure address %d == firstName address %d", testPerson, testPerson->firstName);

Lo que significa que este gratis (testPerson) debe ser igual a esto (testPerson->FirstName);

Y eso no es lo que quiero hacer.

Gracias

Author: user10099, 2012-11-27

7 answers

Respuesta simple: free(testPerson) es suficiente .

Recuerde que puede usar free() solo cuando haya asignado memoria utilizando malloc, calloc o realloc.

En su caso, solo tiene memoria malloced para testPerson, por lo que liberar eso es suficiente.

Si ha utilizado char * firstname , *last surName entonces en ese caso para almacenar nombre debe haber asignado la memoria y por eso tuvo que liberar a cada miembro individualmente.

Aquí también hay un punto que debe estar en el orden inverso; es decir, la memoria asignado para los elementos se hace más tarde por lo que free() primero se libera el puntero al objeto.

Liberando cada elemento se puede ver la demostración que se muestra a continuación:

typedef struct Person
{
char * firstname , *last surName;
}Person;
Person *ptrobj =malloc(sizeof(Person)); // memory allocation for struct
ptrobj->fistname = malloc(n); // memory allocation for firstname
ptrobj->surName = malloc(m); // memory allocation for surName

.
. // do whatever you want

free(ptrobj->surName);
free(ptrobj->firstname);
free(ptrobj);

La razón detrás de esto es, si libera el ptrobj primero, entonces habrá memoria filtrada que es la memoria asignada por los punteros firstname y suName.

 50
Author: Omkant,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-11-28 00:25:18

Debido a que definió el struct como consistiendo en char arrays, las dos cadenas son la estructura y liberar el struct es suficiente, ni hay una manera de liberar el struct pero mantener los arrays. Para ese caso, querrías hacer algo como struct { char *firstName, *lastName; }, pero luego necesitas asignar memoria para los nombres por separado y manejar la pregunta de cuándo liberar esa memoria.

Aparte: ¿Hay una razón que desea mantener los nombres después de que el struct ha sido liberado?

 5
Author: dmckee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-11-27 18:41:10

Primero debe saber cuánta memoria se asigna cuando define y asigna memoria en el caso siguiente.

   typedef struct person{
       char firstName[100], surName[51]
  } PERSON;
  PERSON *testPerson = (PERSON*) malloc(sizeof(PERSON));

1) El sizeof (PERSON) ahora devuelve 151 bytes (No incluye relleno)

2) La memoria de 151 bytes se asigna en heap.

3) Para free, llame a free (testPerson).

Pero si declaras tu estructura como

  typedef struct person{
      char *firstName, *surName;
  } PERSON;
  PERSON *testPerson = (PERSON*) malloc(sizeof(PERSON));

Entonces

1) El sizeof (PERSON) ahora devuelve 8 bytes (No incluye relleno)

2) Necesidad de asignar memoria para nombre y apellido llamando a malloc() o calloc(). como

        testPerson->firstName = (char *)malloc(100);

3) Para liberar, primero libera a los miembros en la estructura que libera la estructura. i. e, gratis (testPerson- > Nombre); gratis (testPerson- > Apellido); libre (testPerson);

 4
Author: Viswesn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-11-27 19:09:59

De esta manera solo necesita liberar la estructura porque los campos son arrays con tamaños estáticos que se asignarán como parte de la estructura. Esta es también la razón por la que las direcciones que ves coinciden: la matriz es lo primero en esa estructura. Si declaras los campos como char * tendrás que manualmente malloc y liberarlos también.

 3
Author: MK.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-11-27 18:42:32

Mallocs y frees necesitan ser emparejados.

Malloc agarró un pedazo de memoria lo suficientemente grande para una Persona.

Cuando usted libera le dice a malloc que el pedazo de memoria que comienza "aquí" ya no es necesario, sabe cuánto asignó y lo libera.

Si llama

 free(testPerson) 

O

 free(testPerson->firstName)

Todo lo que free() recibe en realidad es una dirección, la misma dirección, no puede decir a cuál llamaste. Sin embargo, su código es mucho más claro si usa free(testPerson), claramente coincide con Malloc.

 2
Author: djna,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-11-27 18:41:22

No puedes liberar tipos que no están asignados dinámicamente. Aunque los arrays son sintácticamente similares (int* x = malloc(sizeof(int) * 4) se puede usar de la misma manera que int x[4]), llamar a free(firstName) probablemente causaría un error para este último.

Por ejemplo, tome este código:

int x;
free(&x);

free() es una función que toma un puntero. &x es un puntero. Este código puede compilarse, aunque simplemente no funcione.

Si pretendemos que toda la memoria se asigna de la misma manera, x se "asigna" en el definición, " freed "en la segunda línea, y luego" freed " de nuevo después del final del ámbito. No puedes liberar el mismo recurso dos veces; te dará un error.

Esto ni siquiera menciona el hecho de que por ciertas razones, es posible que no pueda liberar la memoria en x sin cerrar el programa.

Tl; dr: Solo libera el struct y estarás bien. No llame a free en arrays; solo llámelo en memoria dinámicamente asignada.

 2
Author: Undeterminant,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-11-27 19:16:20

free no es suficiente, free solo marca la memoria como no utilizada, los datos de la estructura estarán allí hasta que se sobrescriban. Por seguridad, establezca el puntero en NULL después de free.

Ex:

if (testPerson) {
    free(testPerson);
    testPerson = NULL;
}

struct es similar a una matriz, es un bloque de memoria. Puede acceder al miembro de struct a través de su desplazamiento. El miembro de la primera estructura se coloca en offset 0 por lo que la dirección del miembro de la primera estructura es la misma que la dirección de la estructura.

 2
Author: sdao,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-02 04:38:23