Erreur d'un programme en language C

Résolu/Fermé
flashdumpf Messages postés 17 Date d'inscription lundi 5 janvier 2009 Statut Membre Dernière intervention 14 mai 2010 - 1 mars 2009 à 15:21
 loupius - 1 mars 2009 à 23:00
Bonjour,

j'ai un souci dans mon programme, c'est un exercice qu'on m'a demandé de résoudre. Ce programme est censé créer au max 20 adresses e-mail en ayant donné a chaque fois un nom un prénom et un isp... par exemple

PRENOM: jean
NOM: tagagada
ISP: yahoo.fr

DOIT (énoncé) donner: j.tagagada@yahoo.fr

Le programme doit allouer dynamiquement de la mémoire et l'effacer a la fin... Il doit aussi s'arrêter quand l'utilisateur entre "quit" comme NOM. J'ai marqué les endroits ou il y a qq soucis...

Merci d'avance

****************************
include<stdio.h>
#include<string.h>
#include<malloc.h>
#include<stdlib.h>

#define MAX_ADRESSES 20
#define CNOM 20
#define CPRE 15
#define CISP 25

void Lire_Chaine(char invitation[],int lgmax,char chaine[]){
	char tampon[512];
	printf(invitation);
	gets(tampon);
	tampon[lgmax]='\0';
	strcpy(chaine,tampon);
}

void afficher(char* adresses[],int nb){
	int i;
	for(i=0;i<nb;i++){
		printf("\n Adresse %d : %s",i+1,adresses[i]);
	}

}
void liberer(char* adresses[],int nb){
	int i;
	for(i=0;i<nb;i++){
		free(adresses[i]);
	}
	free(adresses);
}

void main(){
	int i,lg;
	char Nom[CNOM+1], Prenom[CPRE+1], ISP[CISP+1];
			
	// caractères utiles +1 pour le \0

	char* adresses[MAX_ADRESSES];

	i=0;
	while(i<MAX_ADRESSES){
		Lire_Chaine("\nNom suivant ou quit pour terminer: ",CNOM,Nom);
		if(Nom=="quit"){				// Ne marche pas, PQ?
			break;
		}
		Lire_Chaine("Prenom: ",CPRE, Prenom);
		Lire_Chaine("ISP: ",CISP,ISP);
		
		lg=strlen(Nom)+strlen(ISP)+4;		

		// +4 caractères: 1ère lettre du prénom, le point, le @, le \0

		adresses[i]=(char*)malloc(lg*sizeof(char));
		if(!adresses[i]){
			liberer(adresses,i);
			break;
		}
		sprintf(adresses[i],"%c.%s@%s",Prenom[0],Nom,ISP);
		i++;
	}
	afficher(adresses,i);
	liberer(adresses,i);					// Pose probleme, PQ?
}


5 réponses

free(adresses);
Mais aucune allocation n'a été faite pour 'adresses', alors à la libération... ça plante... et c'est normal!!!
2
[o.o]REplay Messages postés 357 Date d'inscription vendredi 20 juin 2008 Statut Membre Dernière intervention 20 juillet 2009 28
1 mars 2009 à 15:36
Le but de cet exo est de te faire comprendre les erreurs à ne pas faire, et cet exercice en est truffé.
On ne va pas le résoudre pour toi, si encore c'est toi qui l'avais fait..

Si tu as du mal en C, vas voir à cette adresse:
https://openclassrooms.com/fr/courses/19980-apprenez-a-programmer-en-c

Sinon compile ton code, et résous les erreurs au fur et à mesure.
0
flashdumpf Messages postés 17 Date d'inscription lundi 5 janvier 2009 Statut Membre Dernière intervention 14 mai 2010 1
1 mars 2009 à 16:21
En fait c'est moi qui ai fait cet exercice...

J'ai déja trouvé une solution au premier probleme:
if(Nom=="quit"){				
	break;
}

Que j'ai remplacer par:
if(!strcmp(Nom,"quit")){
	break;
}

Truffé d'erreur? Le programme m'affiche pourtant les bonnes réponses, j'ai juste qu'une erreur au niveau de la libération de mémoire, une erreur windows:

Debug Assertion Failed!
Expression:_CrtIsValidHeapPointer(pUserData)

En regardant sur Google, je vois que cela a un rapport avec la mémoire allouée dynamiquement, mais je n'arrive pas à trouver où se situe l'erreur...
0
Je reprends la main.
	adresses[i]=(char*)malloc(lg*sizeof(char));
	if(!adresses[i]){
		liberer(adresses,i);
		break;
	}
donc si je comprends bien:
Tu demandes de la mémoire par malloc et si tu n'as pu en obtenir (adresses[i] est 0) alors tu libères la mémoire... qui n'a pas été allouée!!! En général, dans ce genre de situation, on affiche un message de mémoire saturée et... on se tire!!!
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
flashdumpf Messages postés 17 Date d'inscription lundi 5 janvier 2009 Statut Membre Dernière intervention 14 mai 2010 1
1 mars 2009 à 22:27
Effectivement, je ne peux faire de free d'adresse qui n'a pas été alloué avec malloc... je n'y avais pas pensé

Merci

Et pour ce qui est de libérer la mémoire en cas d'échec, c'est le prof qui le veut ainsi... :D
0
Libérer de la mémoire qui n'a pas pu être allouée... désolé mais ton prof a forcément tort mais peut-être n'as-tu pas compris son propos! De là à se tirer pour aller acheter une barette mémoire supplémentaire, il ne faut pas exagérer; on peut effectivement se contenter de ne plus s'obstiner à remplir la mémoire et même parfois attendre qu'un autre programme rende un peu de mémoire...
NB: j'ai un peu exagéré en te charriant au sujet de libérer un pointeur NULL. En effet, selon les dernières implémentations du C, il est possible d'écrire 'free(NULL)' - dans ce cas free ne fait rien -; mais faire un 'free(0)' montre, en général, une mauvaise démarche.
Bonne nuit.
0