Problème en C, aidez moi svp!

Fermé
Djule - 6 nov. 2005 à 02:11
 Djule - 6 nov. 2005 à 20:35
Bonjour, j'ai un petit problème en c
En fait je voudrais créer une fonction qui me renvoie une chaine de caractère, cette chaîne de caractère étant lu aléatoirement dans un fichier.


voila ma premiere ébauche :

char* fonction()
{

	FILE *f;
	int a=rand()%10;
	char* str;
	f=fopen("ressource.txt","r");
	for(int i=0;i<=a; i++)
	{
		fscanf(f,"%s",&str);

	}

	return str;
	
}



Lors de la compilation, ce programme me génére aucun erreur
mais lors de l'execution message d'ERREUR : La mémoire ne peut être "read"

bizarement lorsque je glisse le "return tmp" dans la boucle for le programme s'éxécute sans acun problème. Malheuresement la chaine de caractère renvoyée par la fonction n'est plus mot choisi aléatoirement dans le fichier comme je l'aurais voulu mais le premier du fichier.

Argggggggg!!!!!

Pouvez vous m'aider svp

3 réponses

crabs Messages postés 908 Date d'inscription lundi 18 avril 2005 Statut Membre Dernière intervention 3 août 2008 507
6 nov. 2005 à 08:00
Salut,
Il sort d'où le tmp ?

Lors que tu déclares "char* str;" dans ton programme tu réserves 4o (ou 8o
suivant ton processeur, ton OS, tes options de compil) dans ta pile.
Lorsque "fscanf(f,"%s",&str);" tu dis au processeur de mettre le mot lu dans
ces 4 octets (ou 8).

aparté : compilation 32bits sur Pentium III : 4o, compilation 64bits sur
UltraSparc III : 8o, si tu veux connaitre cette taille affiche sizeof(char*) dans
un petit programme.

Comme la pile fonctionne en mode d'adresse décroissante, si ton mot est plus
long tu va écraser des valeurs dans cette même pile : tu n'a jamais entendu
parlé des attaques de type "dépassement de pile". C'est le début, sauf que
comme tu ne sait pas ce que tu mets comme valeur plutot que de faire un beau
virus, le programme plante.

Le second souci c'est qu'une fois le retour fait, l'espace de la pile est de
nouveau libre, donc même si tous tes mots font moins de 3 caractères, lors
de l'appel à printf par exemple ta pile ne contient plus de valeur correcte.

Dernier souci, tu ne retourne pas l'adresse de ces 4o (ou 8o) mais leur
valeur, soit un pointeur sans sens pour la fonction appelante

Pour cela tu as donc 4 solutions, de la moins 'joli' à la plus 'pro' :
- utiliser une variable globale : char str[TAILLE_MAX] ;
- utiliser une variable statique à la fonction : char str[TAILLE_MAX]
- déclarer la variable dans la fonction appelante et la passer en argument à
la fonction de lecture du fichier
- utiliser l'allocation dynamique de mémoire.
TAILLE_MAX correspond à longeur maximale de tes mots + 1 caractères,
le tout arrondi au multiple de 4 (ou de 8) supérieur le plus proche. ex
en français le mot le plus long 25 lettres : anticonstitutionnellement
donc pour le calcul de TAILLE_MAX:
25+1=26 -> il faut de la place pour le caractère de fin de chaine '\0'
en 4o : on prendra 28 (4x7)
en 8o : on prendra 32 (8x4)
Je te proposes donc un petit code utilisant la seconde méthode :
char* fonction()
  {
  FILE *f;
  int a=rand()%10;
  static char str[28]; /* on lit des mots français sur un processeur 32 bits)
  f=fopen("ressource.txt","r");
  for(int i=0;i<=a; i++)
    fscanf(f,"%s", str);
  return str;
  }

La limite des solution 1 & 2 : on ne peut faire appel qu'une seule fois
à cette fonction, tant qu'on n'a pas copié la valeur retournée dans une
nouvelle chaine de caractères.

A+, crabs
0
Merci beaucoup crabs pour ta clarté et le détail de ton explication.
Peut tu m'en dire un peu plus sur ce qu'est la pile stp
0
crabs Messages postés 908 Date d'inscription lundi 18 avril 2005 Statut Membre Dernière intervention 3 août 2008 507
6 nov. 2005 à 20:28
Salut,
L'explication que je vais essayer de te donner reste assez simple, car je ne
parle pas de l'implémentation physique, comme on devait la faire en
assembleur, ni de la segmentation, ni de la mémoire virtuelle ni de la
rellocation des blocs de données, etc...
Ce sont de vielles notions de programmation des systèmes d'exploitation,
si il y a une révolution dans le principe, je ne suis pas au courant...

Pour simplifier un processus (un programme en train de s'éxécuter) voit sa
memoire découpé en 3 zones :
- la zone du code : qui contient le code exécuté par le processeur
- la zone de données : qui contient les données statiques (zone mémoire
déclarée par le compilateur) et la mémoire dynamique. Cette zone peut
changer de taille au fur et à mesure des allocations dynamiques de mémoire
- la pile.

La pile va contenir :
- les arguments lors des appels de fonctions
- l'adresse de retour dans les fonction appelantes
- l'adresse de début des arguments
- les variables locales à une fonction

La pile et la zone de données change de taille pendant le déroulement du code
du processus. Afin de rendre simple ces 2 accroissements de taille, le choix
le plus commun à été de dire :
-la zone de données croît vers les adresses croissantes et commence à
l'adresse la plus basse disponible
-la pile croit de manière décroissante en partant de l'adresse la plus haute.

La gestion par les systèmes modernes reste plus complexe, car même le code
devient dynamique : bibliothèque dynamique, mais la pile continue à être dans
les adresses hautes.

A+, crabs
0
Encore merci pour toutes tes explication trés détaillées
et... chapeau l'artiste pour toutes tes connaissances!!!!

a+ Djule
0