Réallocation propre ?

Résolu
Utilisateur anonyme -  
 Utilisateur anonyme -
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 11653 Statut Contributeur 1 847
 
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
Utilisateur anonyme
 
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 11653 Statut Contributeur 1 847 > Utilisateur anonyme
 
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
Utilisateur anonyme > fiddy Messages postés 11653 Statut Contributeur
 
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 11653 Statut Contributeur 1 847 > Utilisateur anonyme
 
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
Utilisateur anonyme > fiddy Messages postés 11653 Statut Contributeur
 
Ah ok merci bien :)

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