2010-10-29 4 views
0
#include <stdio.h> 
#include <stdlib.h> 

int main() 
{ 
    int *numeros = malloc(sizeof(int) * 3 * 3); 
    numeros[900] = 10; 
    printf("%d", numeros[900]); 
    free(numeros); 
    return 0; 
} 

Pourquoi exactement cela imprime 10 lorsque je n'ai pas alloué assez de mémoire? Je suis sûr que je manque quelque chose de grand sur les pointeurs/etc.Tableau, allocation, perplexion

Merci de nous aider à

Répondre

14

Ce que vous observez est un comportement non défini - vous écrivez en dehors du tampon alloué et écrasez probablement une mémoire qui se trouve être mappée dans le processus.

En fonction de divers facteurs, cela pourrait bloquer votre programme ou simplement ne rien faire ou corrompre des données dans le programme. Ne le faites pas, accédez uniquement à la mémoire que vous avez légalement allouée.

Voir aussi this related question.

+0

* À moitié gags * il peut aussi écrire '10' dans une partie du système d'exploitation et, à cause de cela, formater votre disque dur :-) – pmg

+0

@pmg: Yeap, ou envoyer tous vos mots de passe sur le réseau - similaire à cette instance UB http://stackoverflow.com/questions/908872/whats-the-worst-example-of-undefined-behaviour-actually-possible/3554343#3554343 – sharptooth

1

La taille de votre tableau est 9. Donc, lorsque vous essayez d'accéder à un emplacement de mémoire 900 qui est hors limites.

Votre comportement est undefined. Ce qui signifie, parfois, il pourrait imprimer des valeurs indésirables, parfois il pourrait tomber en panne. Donc toujours initialiser vos vars avant utilisation.

1

Ce qui vous manque est que le compilateur n'est pas nécessaire pour attraper ce cas, et souvent non. C'est un comportement indéfini, ce qui signifie qu'il n'y a aucune exigence quant à ce que l'implémentation fait, et c'est votre travail de l'éviter. En règle générale, le compilateur compilera simplement ce qu'il voit en cas de comportement indéfini, et le comportement parfois raisonnable qui en résulte peut être déroutant.

Dans ce cas, vous avez enregistré une adresse mémoire dans numeros, et dans la déclaration suivante fait référence *(numeros + 900), qui, étant donné la taille int habituelle serait 3600 octets après l'adresse de mémoire. Le compilateur a généré le code pour la référence. Considérant qu'il s'agit d'un comportement indéfini, le compilateur a parfaitement raison de le faire, ou d'écrire un courriel insultant à vous ou votre mère; la norme ne spécifie rien. Il pourrait, bien sûr, détecter cela et vous donner une erreur d'exécution en disant "Adresse hors limites à la ligne 7", mais malheureusement, aucun des compilateurs que j'ai utilisé ne vous donne cette option.

Ceci est l'une des parties les plus délicates de la programmation C: s'assurer que votre programme est bien défini.

+0

+1: votre message m'a rappelé quelque chose que j'ai lu quelque part: ** Les compilateurs C font confiance au programmeur.** Mentez au compilateur et ça va prendre sa revanche – pmg

0

Vous occupation de la mémoire de 9 éléments avec malloc:

int *numeros = malloc(sizeof(int) * 3 * 3); 
     // allocates memory of (4) *(9) bytes==36 bytes 

Maintenant vos limites du tableau devrait être dans la limite de int est pour que vous la mémoire allouée qui est le numéro par lequel vous avez multiplié votre sizeof (int). Il a alloué de la mémoire pour autant int.

0

Vous pouvez le faire car vous avez affecté votre tableau au tas, qui est probablement d'au moins 32K. Donc, ce que vous faites est d'écrire à un autre endroit dans le tas, ce qui est "légal". Si vous avez augmenté votre index de tableau jusqu'à 128000 ou plus, vous pouvez obtenir une violation d'accès. Comme c'est le cas, vous écrasez (potentiellement) d'autres données que vous avez allouées, ou peut-être les métadonnées de gestion de tas réelles (en-têtes de bloc).