malloc()

malloc() - C++ - Programmation

Marsh Posté le 01-04-2003 à 15:37:05    

quelqu'un saurait-il m'expliquer comment ceci peut fair cela  :??:  :
 

Code :
  1. int main(){
  2. char* S;
  3. sprintf(S, "1234567" );
  4. printf("%s", S);
  5. }


 
-> y me m'affiche "1234567" suivit d'un "segmentation fault"
jusqu'ici tout est logique (j'ai pas alloué de bloc a S)  
 

Code :
  1. int main(){
  2. char* S=malloc(0);
  3. sprintf(S, "1234567" );
  4. printf("%s", S);
  5. }


 
-> mais maintenant ça marche pourtant j'ai alloué 0 bloc!?
pourkoi?
 :??:

Reply

Marsh Posté le 01-04-2003 à 15:37:05   

Reply

Marsh Posté le 01-04-2003 à 15:41:11    

coup de bol

Reply

Marsh Posté le 01-04-2003 à 15:45:28    

Peak a écrit :

quelqu'un saurait-il m'expliquer comment ceci peut fair cela  :??:  :


 
segmentation :o


---------------
brisez les rêves des gens, il en restera toujours quelque chose...  -- laissez moi troller sur discu !
Reply

Marsh Posté le 01-04-2003 à 15:46:27    

Citation :

coup de bol


Disont que theoriquement il est sensé y'avoir un expliquation logique!?


Message édité par peak le 01-04-2003 à 15:47:24
Reply

Marsh Posté le 01-04-2003 à 15:48:11    

ce serait pas du à une optimisation du compilo sur un prog simple ?
 
Bon ... Ce serait vraiment hasardeux, mais bon ...
 
 
tu as fait plusieurs tests ? Parce que ca ressemble à un gros cas particulier quand même ...

Reply

Marsh Posté le 01-04-2003 à 15:54:55    

dans le cas du char* S, S pointe n'importe où (car il est pris sur la pile qui contiens des valeurs aléatoires).
 
si hors de l'espace virtuel => seg fault.
 
dans le cas de char* S=malloc(0), à priori un NULL est retourné.
forcément dans l'espace virtuel => écrasement du début du segment de donnée...
 
je vois ça comme ça....

Reply

Marsh Posté le 01-04-2003 à 15:56:54    

NULL ne fait pas partie de l'espace d'adressage (au moins sous win), les access violation sur l'adresse 0x0 j'en ai vu un paquet :D

Reply

Marsh Posté le 01-04-2003 à 15:58:24    

C'est sur que le compilo te jette dès que tu fais un accès à l'adresse 0 ! :D

Reply

Marsh Posté le 01-04-2003 à 16:00:40    

sinon jeu interressant (pas essayé perso) :
penser à désactiver les optimisations, notemment l'inline automatique:

Code :
  1. affiche()
  2. {
  3.   char *S;
  4.   puts(S);
  5. }
  6. saisi()
  7. {
  8.   char *S;
  9.   gets(S);
  10. }
  11. alloue()
  12. {
  13.   char *S=malloc(100);
  14. }
  15. // version qui pourrait marcher
  16. main()
  17. {
  18.   alloue();
  19.   saisi();
  20.   affiche();
  21. }
  22. // version encore plus drôle;
  23. char machin[]="wesh yo wesh";
  24. push_machin()
  25. {
  26.   char *S=machin;  // faudrait être sûr que l'offset soit pushé :/
  27. }
  28. main()
  29. {
  30.   push_machin();
  31.   saisi();
  32.   puts(machin);
  33. }

Reply

Marsh Posté le 01-04-2003 à 16:01:07    

chrisbk a écrit :

NULL ne fait pas partie de l'espace d'adressage (au moins sous win), les access violation sur l'adresse 0x0 j'en ai vu un paquet :D


 
bin temps pi alors  [:the one]

Reply

Marsh Posté le 01-04-2003 à 16:01:07   

Reply

Marsh Posté le 01-04-2003 à 16:03:45    

[citation=349285,1]
  char *S=machin;  // faudrait être sûr que l'offset soit [/citation]
 
il doit te manquer un gros cast des familles ! ;)
 
mais ca peut être fun ! :D

Reply

Marsh Posté le 01-04-2003 à 16:05:51    

theShOcKwAvE a écrit :

ce serait pas du à une optimisation du compilo sur un prog simple ?
 
Bon ... Ce serait vraiment hasardeux, mais bon ...
 
 
tu as fait plusieurs tests ? Parce que ca ressemble à un gros cas particulier quand même ...


 
apparement ça marche pour une string de n'importe quel taille et si je fait :
 

Code :
  1. int main(){
  2. char* S=malloc(3);
  3. sprintf(S, "1234567" );
  4. printf("%s", S);
  5. }

 
 
j'ai 3blocs aloué et je met 8 (ou même 20)char ça marche toujours??
 

Reply

Marsh Posté le 01-04-2003 à 16:08:21    

wé mais comme les OS fonctionnent par pages de 4Ko ou 4Mo en x86, le seg fault ne peut se déclencher que par rapport à cette granularité....
 
de plus je sais aps si les malloc ont une granularité....

Reply

Marsh Posté le 01-04-2003 à 16:14:07    

Ca me dérange quand même qu'il ne te jette pas dès que tu fais le sprintf .... Un accès en écriture n'importe où, t'as peu de chances que ca passe .... Encore moins de chance que de réussir une lecture au même endroit, d'ailleurs ! ;)

Reply

Marsh Posté le 01-04-2003 à 16:39:50    

je vous avoue que j'aurai aussi préferé me fair jetter dès que je fais le sprintf  (c'étai d'ailleur mon but quand j'ai testé)
 
Au moins j'aurai eu l'imprétion de comprendre quelque chose :D  

Reply

Marsh Posté le 03-04-2003 à 09:15:13    

Il suffit de savoir comment fonctionne malloc pour comprendre :-)
 
En fait, chaque processus possede un espace d'adresse virtuel. Cet espace est separe en 3 parties : pile, text et data. C'est dans cette derniere partie que sera stockees tous nos donnes dynamiques. Pour definir la taille de cette zone, il faut deplacer un "break" (man sbrk).
 
Si l'on demande 12 octets, malloc va deplacer le break de bien plus pour d'une part stocker ses propres informations (taille du bloc allouee), et d'autre part pour "bufferiser" les appels a sbrk (appel systeme couteux en temps).
 
Or pour faire un segfault, il fait etre en dehors du data (avant le edata ou derriere le brk)...
 
Voila qui explique certaines chose  :)  


---------------
Teuf Corp. - Just Mix'It.
Reply

Marsh Posté le 03-04-2003 à 09:18:21    

Tu ne serais pas en mode debug par hasard ?
Il me semble que j'avais lu que dans ce mode, certain compilo (Visual pour ne pas le citer) allouait un peu plus que demandé pour éviter les dépassement de tableau.


Message édité par pascal_ le 03-04-2003 à 09:18:45
Reply

Marsh Posté le 03-04-2003 à 10:50:46    

pascal_ a écrit :

Tu ne serais pas en mode debug par hasard ?
Il me semble que j'avais lu que dans ce mode, certain compilo (Visual pour ne pas le citer) allouait un peu plus que demandé pour éviter les dépassement de tableau.


 
debug ou pas, malloc alloue toujours plus que ce que tu lui demandes. Tu n'as pas lu mon post a ce sujet ?


---------------
Teuf Corp. - Just Mix'It.
Reply

Marsh Posté le 03-04-2003 à 11:20:55    

Kyser a écrit :


 
debug ou pas, malloc alloue toujours plus que ce que tu lui demandes. Tu n'as pas lu mon post a ce sujet ?


 
Un petit tour sur msdn :  
[link]
http://msdn.microsoft.com/library/ [...] g_Heap.asp
[/link]
 
On trouve :  
 
"For example, suppose your application contains the call: malloc( 10 ).
In a Release build, malloc would call the base heap allocation routine requesting an allocation of 10 bytes.  
In a Debug build, however, malloc would call _malloc_dbg, which would then call the base heap allocation routine requesting an allocation of 10 bytes plus approximately 36 bytes of additional memory."
 
 
Donc, voila : en debug visual alloue plus que tu lui demande (environ 36 bytes pour les opérations de debug).
 
Et TOC !


Message édité par pascal_ le 03-04-2003 à 11:27:07
Reply

Marsh Posté le 03-04-2003 à 11:48:59    

oui mais le monsieur te décrit comment ça se passe au niveau os sur sous unix/linux.
à priori windows devrait +ou- faire la même chose (granularité sur le segment de donnée)

Reply

Marsh Posté le 03-04-2003 à 13:25:12    

BJOne a écrit :

oui mais le monsieur te décrit comment ça se passe au niveau os sur sous unix/linux.
à priori windows devrait +ou- faire la même chose (granularité sur le segment de donnée)


 
Je suis d'accord avec le monsieur pour la granularité.
 
Cependant si le type avec visual en mode debug fait  

Code :
  1. int main(){
  2. char* S=malloc(0);
  3. sprintf(S, "1234567" );
  4. printf("%s", S);
  5. }

 
visual alloue n'ont pas un block de 0 mais un block de 36.
Donc si le prog ne plante pas ce n'est pas à cause de la granularité (par contre, en mode release, si).

Reply

Marsh Posté le 04-04-2003 à 00:47:10    

ouki doki....
 

Reply

Marsh Posté le 04-04-2003 à 01:29:25    

pascal_ a écrit :


 
Je suis d'accord avec le monsieur pour la granularité.
 
Cependant si le type avec visual en mode debug fait  

Code :
  1. int main(){
  2. char* S=malloc(0);
  3. sprintf(S, "1234567" );
  4. printf("%s", S);
  5. }

 
visual alloue n'ont pas un block de 0 mais un block de 36.
Donc si le prog ne plante pas ce n'est pas à cause de la granularité (par contre, en mode release, si).
 


 
 
Tu n'as pas bien compris, et mon message, et MSDN.
 
"In a Release build, malloc would call the base heap allocation routine requesting an allocation of 10 bytes."
 
Or, la "base heap allocation routine", alloue FORCEMENT plus que les octets que tu lui demandes, pour stocker des informations indispensable a malloc. Ne serait-ce que la taille du bloc (utilise pour les appels a FREE).  
 
Sinon comment que tu crois que malloc retrouve ts les pointeurs alloue ?
 
De plus l'alignement des donnes fait que tu auras tjs plus d'octets que demande (mais c'est transparant et il ne faut pas se baser dessus). Exemple avec 10, tu devrais tomber sur 12 ou 16 octets.
 
En fait je parlais plus de l'exemple  
 

Code :
  1. char *s  = malloc(3);
  2. strcpy(s, "coucou ca va ?" );

 
 
qui ne segfault pas.
 
Pour l'exemple avec malloc(0), sous unix cela amenerait directement a un segfault, et visiblement sous Windows non ... peut-etre a cause du debug effectivement.


---------------
Teuf Corp. - Just Mix'It.
Reply

Marsh Posté le 04-04-2003 à 01:31:32    

Petite precision sur l'explication de malloc pour ceux que ca interesse :
 
Pour les grosses allocations, malloc fait plutot appel a mmap que sbrk, ce dernier etant beaucoup plus couteux en terme de performances.
 
Voila  :hello:


---------------
Teuf Corp. - Just Mix'It.
Reply

Marsh Posté le 04-04-2003 à 08:38:22    

Citation :

Pour l'exemple avec malloc(0), sous unix cela amenerait directement a un segfault, et visiblement sous Windows non ... peut-etre a cause du debug effectivement.


 
par contre y'a gros risque d'assert au moment du free...
 
Perso g jamais compris l'interet de cette histoire de debug, je prefere avoir une grosse exception au moment precis ou j'ecris n'imo en ram plutot qu'un assert en fin de prog pour dire que plus tot j'ai fin n'imp....
 
 
edit : ou c'est justement parce que on alloue la memoire que par block .... [:meganne]


Message édité par chrisbk le 04-04-2003 à 08:38:43
Reply

Marsh Posté le 07-04-2003 à 22:39:10    

C'est pas du clustering mémoire ?
 
ou alors si cet espace n'est pas réservé par une autre applic/fct, il te jette pas.
 
par exemple
 

Code :
  1. char s[10] ;
  2. s[5] = 'l' ;
  3. s[12] = 's' ;    // ça passe... écriture en dehors des bornes


 
A mon avis, il te laisse écrire (pas longtemps mais quand même)

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

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