2010-02-28 6 views
8

Je pourrais être stupide et vous devez m'excuser dans ce cas ... mais je ne comprends pas. J'alloue un buffer de 16 caractères puis (dans une boucle for) mets 23 (!?) caractères aléatoires et ensuite j'imprime ce truc. Ce que je ne comprends pas, c'est comment je peux mettre 23 caractères dans un tampon qui est mallocé en 16 caractères ... Quand je change la boucle à 24 caractères, je reçois une erreur (au moins sous Linux avec gcc) ... mais pourquoi ne pas « plus tôt » (17 caractères doivent casser ... pas)Pas d'erreur même lorsque je dépasse la limite de la mémoire allouée?

Ceci est mon exemple de code:

#include <stdio.h> 
#include <stdlib.h> 

int main() 
{ 
    int n; 
    char *buf; 

    buf = malloc(16 * sizeof(*buf)); 
    if(buf == NULL) exit(1); 

    for(n = 0; n < 22; n++) 
    { 
     buf[n] = rand()%26+'a'; 
    } 
    buf[n]='\0'; 

    printf("Random string: %s\n", buf); 

    free(buf); 
    buf = NULL; 

    getchar(); 
    return 0; 
} 
+0

Probablement un doublon: http://stackoverflow.com/questions/1240970/c-why-do-you-specify-the-size-when-using-malloc http://stackoverflow.com/questions/2336796/ weird-behavior-of-malloc – bk1e

Répondre

4

La plupart des stratégies d'allocation de mémoire arrondissent votre requête malloc jusqu'à une certaine valeur de quantification. Souvent 16 ou 32 octets. Cette quantification se produit généralement après que l'allocateur a ajouté dans son overhead (utilisé pour garder une trace des blocs alloués), donc il est courant de trouver que vous pouvez surcharger un malloc par un petit nombre d'octets sans causer de dommages réels au tas, en particulier lorsque la taille d'allocation est impaire.

Bien sûr, ce n'est pas quelque chose dont vous voulez dépendre, c'est un détail d'implémentation de la bibliothèque c runtime, et sujet à changement sans préavis.

+1

Merci pour votre réponse. –

6

Vous produisez une erreur, mais comme de nombreux bugs il arrive juste de ne pas être remarqué. C'est tout ce qu'on peut en dire. Cela peut être dû à l'une des raisons suivantes - probablement que la structure du magasin libre présente un espace entre les allocations car le système a besoin (ou veut) de conserver les adresses des blocs allouables alignées sur certaines limites. Donc écrit un peu passé votre bloc alloué ne pas interférer avec les structures de données de magasins gratuits, mais un peu plus loin et ils le font.

Il est également tout à fait possible que votre bogue ait corrompu quelque chose que le responsable du magasin libre utilisait, mais il ne s'est simplement pas réellement utilisé dans votre programme simple, donc l'erreur n'a pas été remarquée.

+5

Pour clarifier - l'OP est probablement utilisé pour les langages de plus haut niveau, où de telles erreurs sont détectées. C est délibérément dangereux, et un tel comportement en C est appelé "comportement indéfini" par la norme, ce qui signifie que le code peut faire tout ce qu'il veut. La plupart du temps, il fera la chose la plus simple possible, c'est-à-dire ignorer le fait que vous n'êtes pas autorisé à écrire dans cet espace et à le faire de toute façon. C'est la principale raison pour laquelle C est si difficile - il n'y a rien qui vous contrôle lorsque vous faites quelque chose de mal. –

+1

Bon point, Chris. –

+1

Merci beaucoup pour vos réponses. –

0

En C, vous ferez ce genre de choses. Quelque temps plus tard, d'autres parties des programmes peuvent entrer et écraser la zone que vous n'êtes pas censé utiliser. Il est donc préférable de ne pas tester ces choses.

1

Le comportement lorsque vous débordez un tampon dans C est indéfini. Donc tout peut arriver, y compris rien. Plus précisément, C n'est pas requis et est conçu intentionnellement pour ne pas effectuer de vérification des limites.

Si vous obtenez une erreur d'exécution, c'est généralement parce qu'elle a été détectée et interceptée par le système d'exploitation, et non par le moteur d'exécution C. Et cela ne se produira que si l'accès empiète sur la mémoire non mappée au processus. Plus souvent, il accèdera simplement à la mémoire appartenant à votre processus mais qui peut être utilisée par d'autres objets mémoire; le comportement de votre programme dépendra alors de ce que votre code fait avec les données invalides.

Questions connexes