sprintf et mémoire

sprintf et mémoire - C - Programmation

Marsh Posté le 30-03-2006 à 20:10:18    

Bonjour,
 

Code :
  1. for (i=0; i<16; i++) { // On converti la chaine MD5
  2.  sprintf (pRet, "%s%02x", pRet, digest [i]);
  3. }


 
Ceci est censez me remplir pRet d'une chaine MD5 (32 caractères).
Je lui allou donc sizeof(char)*32.
 
Le probleme c'est que je segfault et que dans pRet j'ai n'importe quoi en début de chaine.
Je pense que cela est dû à que sprintf li et écrit sur un pointeur en meme temps.
 
Quelle solution ?
 
Merci

Reply

Marsh Posté le 30-03-2006 à 20:10:18   

Reply

Marsh Posté le 30-03-2006 à 21:04:28    

Citation :

Je lui allou donc sizeof(char)*32.


 
malloc(33), en comptant le caractere nul en fin de chaine
l'allocation dynamique est vraiment nécéssaire ?
 
tu veux pas plutot faire
 

for (i=0; i<16; i++) { // On converti la chaine MD5
  sprintf (pRet + i*2, "%02x", digest [i]);
}

Reply

Marsh Posté le 30-03-2006 à 21:06:41    

Si pRet n'est pas initialisé au début, ça va t'écrire ce qu'il y a en mémoire jusqu'à ce que ça trouve un char à 0.
 
Ca peut mener très loin dans la mémoire... jusqu'à un segfault.
 
Et mettre à NULL pRet n'est pas une solution non plus, parce que ...printf() réagit assez mal aux pointeurs NULL :D
 
La solution est, après avoir alloué pRet, de l'initialiser avec le premier bout de ta chaîne, puis de faire ta boucle sur 16-1 itérations.
 
Autre chose : il faut lui allouer "(32 + 1) * sizeof char" à pRet, pour pouvoir y stocker le caractère \0 terminal.

Reply

Marsh Posté le 30-03-2006 à 21:42:34    

char *pRet = malloc(sizeof(char) * (32 + 1));
 pRet[0] = '\0';
 
avec le pRet[0] = '\0'; je n'est plus les reste de mémoire.
Mais comment se fait il qu'après un malloc, si j'affiche le contenu de la variable il ya des débris de mémoire ?
 
Et non l'allocation dynamique n'est pas nécéssaire mais si je fait char pRet[33]; comment je peut le return ?


Message édité par Dinan le 30-03-2006 à 21:45:50
Reply

Marsh Posté le 30-03-2006 à 21:50:47    

Je seconde Skelter. Je pense donc aussi que le malloc n'est pas nécessaire dans ce cas, et pourrait être avantageusement remplacé par une réservation sur la pile par un simple

char pRet[33];

Pour avoir juste une petite idée de la complexité qui se cache derrière un simple appel de la fonction malloc(), lire http://www-128.ibm.com/developerwo [...] /l-memory/ et plus spécifiquement les liens en bas de l'article pour des implémentations sur des environnements particuliers.
Edit : Je viens de voir la question pour le return, et il suffit allors de déclarer la variable avec le scope nécessaire, en l'occurence en dehors de la fonction pour qu'elle soit visible depuis la fonction appelante. Habituellement, c'est même la fonction appelante qui fait la réservation mémoire, et qui passe le pointeur à la fonction (comme le propose aussi Trap D).


Message édité par olivthill le 30-03-2006 à 21:55:30
Reply

Marsh Posté le 30-03-2006 à 21:53:05    

Tu peux passer un tableau de caractères assez grand en paramètre de ta fonction et écrire dedans, comme ça pas de problème de return.
D'autre part, sizeof(char) = 1 par définition.


Message édité par Trap D le 30-03-2006 à 22:01:55
Reply

Marsh Posté le 30-03-2006 à 22:05:26    

et dans ce cas vu que la tailles est fixe, on peut prototyper la fonction de maniere à ce qu'elle ne recoivent que l'adresse de ce type de tableau
 

Code :
  1. void func(char (*tab)[33])
  2. {
  3. /*
  4. sizeof *tab == 33
  5. */
  6. strcpy(*tab, ...);
  7. }
  8. int main()
  9. {
  10. char tab[33];
  11. func(&tab);
  12. }

Reply

Marsh Posté le 30-03-2006 à 22:07:11    

Merci tous cela marche, mais pourquoi ma variable n'est pas vide après l'avoir initialisé ? (valeur aléatoire de la mémoire)

Reply

Marsh Posté le 30-03-2006 à 22:10:34    

c'est le pointeur que tu initialise avec une adresse, pas la zone mémoire pointée
pour initiliser la zone mémoire pointée tu peux allouer avec calloc utiliser memset

Reply

Marsh Posté le 30-03-2006 à 22:17:21    

char SESSID[33];
SESSID[0] = '\0';
 
En faisant la mon sprintf ne déconne plus, je sait pas si c'est très propre, mais je vais opter pour cette solution.
 
Merci à vous.

Reply

Marsh Posté le 30-03-2006 à 22:17:21   

Reply

Marsh Posté le 30-03-2006 à 22:28:15    

tu peux faire directement
char SESSID[33] = "";

Reply

Marsh Posté le 30-03-2006 à 22:43:22    

Reply

Marsh Posté le 30-03-2006 à 23:04:18    

Dinan a écrit :


Code :
  1. sprintf (pRet, "%s%02x", pRet, digest [i]);
  2. }


Je pense que cela est dû à que sprintf li et écrit sur un pointeur en meme temps.


Exactement. Il y a recouvrement, ce n'est pas permis. Il faut une variable intermédiaire.


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed