Disons que j'ai cette structure
typedef struct person{
char firstName[100], surName[51]
} PERSON;
et j'alloue de l'espace par malloc et le remplit avec quelques valeurs
PERSON *testPerson = (PERSON*) malloc(sizeof(PERSON));
strcpy(testPerson->firstName, "Jack");
strcpy(testPerson->surName, "Daniels");
Quel est le moyen correct et sûr de libérer toute la mémoire prise par cette structure? Est "gratuit (testPerson);" assez ou dois-je libérer chaque attribut de struct?
Cela m'amène à une autre question: comment les structures sont-elles stockées dans la mémoire? J'ai remarqué un comportement étrange: lorsque j'essaie d'imprimer une adresse de structure, elle est égale à l'adresse de son premier attribut.
printf("Structure address %d == firstName address %d", testPerson, testPerson->firstName);
Ce qui signifie que ce libre (testPerson) doit être égal à ce libre (testPerson-> firstName);
et ce n'est pas ce que je veux faire.
Merci
Réponse simple: free(testPerson)
suffit.
N'oubliez pas que vous ne pouvez utiliser free()
que lorsque vous avez alloué de la mémoire à l'aide de malloc
, calloc
ou realloc
.
Dans votre cas, vous n’avez que de la mémoire mallocalisée pour testPerson
et le libérer est donc suffisant.
Si vous avez utilisé char * firstname , *last surName
, Dans ce cas, pour stocker le nom, vous devez avoir alloué la mémoire et vous devez donc libérer chaque membre individuellement.
Voici aussi un point qui devrait être dans l’ordre inverse; cela signifie que la mémoire allouée aux éléments est effectuée ultérieurement, donc free()
libère ensuite le pointeur sur object.
En libérant chaque élément, vous pouvez voir la démo ci-dessous:
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 raison derrière ceci est que, si vous libérez d'abord le ptrobj
, il y aura une fuite de mémoire, c'est-à-dire la mémoire allouée par les pointeurs firstname
et suName
.
Étant donné que vous avez défini le struct
comme étant constitué de tableaux char
, les deux chaînes are la structure et le fait de libérer le struct
sont suffisants. moyen de libérer le struct
mais gardez les tableaux. Dans ce cas, vous voudriez faire quelque chose comme struct { char *firstName, *lastName; }
, mais vous devez ensuite allouer de la mémoire pour les noms séparément et régler la question de savoir quand libérer that memory.
De plus, y a-t-il un motif vous voulez conserver les noms après la libération de struct
?
Tout d'abord, vous devez savoir combien de mémoire est allouée lorsque vous définissez et allouez de la mémoire dans le cas ci-dessous.
typedef struct person{
char firstName[100], surName[51]
} PERSON;
PERSON *testPerson = (PERSON*) malloc(sizeof(PERSON));
1) Le sizeof (PERSON) renvoie maintenant 151 octets (n'inclut pas le remplissage)
2) La mémoire de 151 octets est allouée dans le tas.
3) Pour libérer, appelez gratuitement (testPerson).
mais si vous déclarez votre structure comme
typedef struct person{
char *firstName, *surName;
} PERSON;
PERSON *testPerson = (PERSON*) malloc(sizeof(PERSON));
puis
1) Le sizeof (PERSON) renvoie maintenant 8 octets (n'inclut pas le remplissage)
2) Besoin d'allouer de la mémoire pour firstName et surName en appelant malloc () ou calloc (). comme
testPerson->firstName = (char *)malloc(100);
3) Pour libérer, commencez par libérer les membres de la structure, puis libérez-la. c'est-à-dire libre (testPerson-> firstName); libre (testPerson-> surName); libre (testPerson);
De cette façon, il vous suffit de libérer la structure car les champs sont des tableaux de tailles statiques qui seront alloués dans le cadre de la structure. C'est aussi la raison pour laquelle les adresses que vous voyez correspondent: le tableau est la première chose dans cette structure. Si vous déclarez les champs comme char *, vous devrez manuellement malloc et les libérer.
Les mallocs et les libérés doivent être jumelés.
malloc a saisi un morceau de mémoire assez gros pour Person.
Lorsque vous libérez, vous indiquez à malloc que la mémoire commençant par "ici" n’est plus nécessaire, elle sait combien de temps elle a allouée et la libère.
Si vous appelez
free(testPerson)
ou
free(testPerson->firstName)
tout ce que free () reçoit réellement est une adresse, la même adresse, elle ne peut pas dire laquelle vous avez appelée. Votre code est beaucoup plus clair si vous utilisez free (testPerson) - il correspond clairement à celui de malloc.
Vous ne pouvez pas libérer des types qui ne sont pas alloués dynamiquement. Bien que les tableaux soient syntaxiquement similaires (int* x = malloc(sizeof(int) * 4)
peut être utilisé de la même manière que int x[4]
Est), appeler free(firstName)
provoquerait probablement une erreur pour ce dernier.
Par exemple, prenons ce code:
int x;
free(&x);
free()
est une fonction qui prend un pointeur. &x
Est un pointeur. Ce code peut compiler, même s'il ne fonctionne tout simplement pas.
Si nous prétendons que toute la mémoire est allouée de la même manière, x
est "alloué" à la définition, "libéré" à la deuxième ligne, puis "libéré" à la fin de la portée. Vous ne pouvez pas libérer deux fois la même ressource; ça va vous donner une erreur.
Cela ne mentionne même pas le fait que pour certaines raisons, vous ne pourrez peut-être pas libérer la mémoire à x
sans fermer le programme.
tl; dr: Libérez simplement le struct
et tout ira bien. Don't appelez gratuitement sur les tableaux; appelez-le uniquement sur la mémoire allouée dynamiquement.
free
ne suffit pas, free
marque simplement la mémoire comme étant inutilisée, les données de structure y resteront jusqu'à ce qu'elles soient écrasées. Par sécurité, définissez le pointeur sur NULL
après free
.
Ex:
if (testPerson) {
free(testPerson);
testPerson = NULL;
}
struct
ressemble à un tableau, c'est un bloc de mémoire. Vous pouvez accéder au membre struct via son offset. Le premier membre de la structure est placé à offset 0
donc l'adresse du membre de la première structure est la même que l'adresse de la structure.