Réallocation propre ?

Résolu
bizu53 Messages postés 1274 Date d'inscription   Statut Membre Dernière intervention   -  
bizu53 Messages postés 1274 Date d'inscription   Statut Membre Dernière intervention   -
Bonjour,

J'ai un bout de code en langage C que j'ai fait pour tester une réallocation dynamique. Je n'ai pas pour habitude de faire ça mais là j'y suis contraint...
Mon bout de code marche parfaitement bien mais je me demande si ma façon de faire (avec les free()) est "propre" :

#include <stdio.h>

int main() {
	char **list; //liste de chaines de caractères
	int i; //indice de parcours
	int nb; //longueur de la liste

	printf("nb = %d :\n", nb = 10);

	list = (char**) malloc(nb*sizeof(char*));
	for(i = 0 ; i < nb ; i++) {
		list[i] = (char*) malloc(250*sizeof(char));
		sprintf(list[i], "chaine %d", i);
	}
	
	for(i = 0 ; i < nb ; i++) printf("%s\n", list[i]);

	for(i = 0 ; i < nb ; i++) free(list[i]);
	free(list);

	printf("\n");

	printf("nb = %d :\n", nb = 20);
	list = (char**) malloc(nb*sizeof(char*));
	for(i = 0 ; i < nb ; i++) {
		list[i] = (char*) malloc(250*sizeof(char));
		sprintf(list[i], "chaine %d", nb-10-i);
	}

	for(i = 0 ; i < nb ; i++) printf("%s\n", list[i]);
}


Dans le cas où ça ne serait pas "propre", quelle est la façon la plus propre de faire cela ?

Merci par avance

1 réponse

fiddy Messages postés 11069 Date d'inscription   Statut Contributeur Dernière intervention   1 846
 
Salut,
Tout d'abord tu as oublié d'inclure <stdlib.h>. Ce qui peut te valoir te jolis bugs ^^.
Ensuite, la règle est simple pour les free. Tu dois en avoir autant que de malloc (ou calloc).
Donc quand tu fais un liste[i]=malloc(5); on doit voir plus loin free(liste[i]);
Tu peux utiliser une boucle for pour parcourir tous les i, et tu mets ton free dedans.
Et enfin au dernier moment, tu fais free(liste);
Tu auras tout désalloué comme ça.
Sinon, pour réallouer des blocs, il y a une fonction tout prête : realloc ;) Et ça t'évitera même de redéfinir tous tes blocs qui n'ont pas lieu de changer, car la fonction s'occupe de tout.
0
bizu53 Messages postés 1274 Date d'inscription   Statut Membre Dernière intervention   861
 
En effet je n'avais pas fait attention que j'ai oublié la première ligne en copiant-collant ^^.
Donc, si j'ai bien compris, je le fais correctement ?
Et je peux enchaîner un nouveau malloc derrière la désallocation propre ? je n'ai pas bien compris ta dernière phrase.. C'est toujours propre ça ? Pourquoi realloc si malloc alloue ?
0
fiddy Messages postés 11069 Date d'inscription   Statut Contributeur Dernière intervention   1 846 > bizu53 Messages postés 1274 Date d'inscription   Statut Membre Dernière intervention  
 
Oui tu l'as fait proprement, hormis le fait que t'as oublié de tester le retour de malloc, l'allocation peut échouer. Par exemple après une allocation, tu peux mettre : if(liste[i]==NULL) exit(EXIT_FAILURE);
Sinon pourquoi realloc ? Voici un exemple :
char *t=malloc(10);
if(t==NULL) exit(EXIT_FAILURE);
strncmp(t,"coucou",sizeof t);

//version malloc
free(t);
if((t=malloc(15))==NULL) exit(EXIT_FAILURE);
strncmp(t,"coucou",sizeof t);

//version realloc
if((t=realloc(t,15))==NULL) exit(EXIT_FAILURE);

Ces deux versions sont équivalentes. Dans la première (malloc), tu dois faire un free, malloc, et recopier le contenu (si tu en as).
Dans la seconde version : un simple realloc suffit.

A noter qu'il ne faudra pas oublier dans les deux cas cas de faire un free(t) avant le return 0; final. (Autant de malloc que de free :p)
0
bizu53 Messages postés 1274 Date d'inscription   Statut Membre Dernière intervention   861 > fiddy Messages postés 11069 Date d'inscription   Statut Contributeur Dernière intervention  
 
Ok merci j'ai compris maintenant :) en tout cas pour une dimension.
J'imagine que le realloc réalloue du même type que dans la première allocation mais fait-il aussi l'allocation mémoire pour une 2ème dimension ?
Dans mon cas je fais un double malloc car j'ai dimensions, je peux faire directement le realloc sur la première dimension ? (la 2ème dimension ne varie pas dans mon cas car j'alloue une taille max pour mes chaînes de caractères constante)

est-ce que je dois réallouer avec malloc la 2ème dimension après un realloc sur la première ?

char **list = (char**) malloc(10*sizeof(char*));
int i;
for(i = 0 ; i < 10 ; i++) {
	list[i] = (char*) malloc(250*sizeof(char));
	sprintf(list[i], "chaine %d", i);
}

realloc(list, 20);


Est-ce que les list[i] de 10 à 19 ont bien subits leur (char*) malloc(250*sizeof(char)); ?
0
fiddy Messages postés 11069 Date d'inscription   Statut Contributeur Dernière intervention   1 846 > bizu53 Messages postés 1274 Date d'inscription   Statut Membre Dernière intervention  
 
Oui, voilà pourquoi je te conseillais realloc ;)
char **list = (char**) malloc(10*sizeof(char*));
int i;
for(i = 0 ; i < 10 ; i++) {
	list[i] = (char*) malloc(250*sizeof(char));
	sprintf(list[i], "chaine %d", i);
}

list=realloc(list, 20);

Je t'ai mis en gras un petit manque de ta part ;) realloc te donne un pointeur générique sur la nouvelle zone allouée. Donc il ne faut surtout pas oublier de récupérer.
Et n'oublie pas de tester si le pointeur est différent de NULL comme dans mes exemples précédents avec if(list==NULL) exit(EXIT_FAILURE); sinon tu pourras avoir des segfault sans comprendre pourquoi ^^.
0
bizu53 Messages postés 1274 Date d'inscription   Statut Membre Dernière intervention   861 > fiddy Messages postés 11069 Date d'inscription   Statut Contributeur Dernière intervention  
 
Ah ok merci bien :)

(je voulais pas me taper une liste chaînée quand une simple réallocation suffisait)
0