2011-03-17 7 views
0

j'utilise VS08 pour construire/exécuter le C++ code suivant:realloc ne pas affecter

#include <stdlib.h> 

struct Header 
{ 
    int count; 
}*lstHeader=NULL; 

int main() 
{ 
    for(int i=0;i<10;i++) 
    { 
     lstHeader=(Header*)realloc(lstHeader,sizeof(Header)+i); 
     lstHeader[i].count=i; 
    } 
    return 1; 
} 

et après l'exécution je reçois l'exception VS suivante:

Windows has triggered a breakpoint in MyProgram.exe. 

This may be due to a corruption of the heap, which indicates a bug in 
MyProgram.exe or any of the DLLs it has loaded. 

This may also be due to the user pressing F12 while MyProgram.exe has focus. 

The output window may have more diagnostic information. 

j'ai essayé de malloc lstHeader au lieu de l'assigner à NULL, mais la même exception VS est survenue et je ne peux pas y figurer.

Répondre

8

Vous devez penser à ce qui se passe lorsque i arrive à 1. Supposons un entier de quatre octets.

A i == 0, vous allouez suffisamment d'octets pour un Header plus un octet zéro supplémentaire. Ensuite, vous définissez Header[0].count à 0. Aucun problème, vous avez seulement changé les quatre octets que vous avez alloués.

A i == 1, vous allouez suffisamment d'octets pour un Header plus un octet supplémentaire (pour un total de cinq octets). Ensuite, vous définissez Header[1].count sur 1. Cela modifie les octets 4, 5, 6 et 7 (zéro) de votre bloc de mémoire en dépit du fait que vous avez seulement des octets 0 à 4 à votre disposition. En d'autres termes, cette opération nécessitait un supplément de quatre octets plutôt que le un octet supplémentaire demandé.

regardant graphiquement:

  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
      | | | | | | | | | | |1|1|1|1|1|1|1|1|1|1|2|2|2|2| 
offset: |0|1|2|3|4|5|6|7|8|9|0|1|2|3|4|5|6|7|8|9|0|1|2|3| 
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
i=0, get: <-------> 
    use: <-------> 
i=1, get: <---------> 
    use: <---------------> 
i=2, get: <-----------> 
    use: <-----------------------> 
i=3, get: <-------------> 
    use: <-------------------------------> 
i=4, get: <---------------> 
    use: <---------------------------------------> 
i=5, get: <-----------------> 
    use: <-----------------------------------------------> 

Comme vous pouvez le voir, chaque itération vous donne un octet supplémentaire, mais vous besoin un quatre octets supplémentaires. Maintenant, cela peut effectivement fonctionner pendant un certain temps, puisque la plupart des appels malloc vous donnent une résolution minimale de 16 octets (demander 1, 2, 3 ou 16 et vous obtenez 16, demander 20 ou 30, vous obtenez 32). Mais le comportement reste indéterminé et vous ne devriez pas compter dessus.

Et, dans tous les cas, vous finirez par arriver au point où cela n'aidera plus. Ce point est où le sizeof*(i+1) dont vous avez besoin dépasse un seuil de 16 octets tandis que le sizeof+i que vous avez demandé reste en dessous. Ensuite, vous allez écrire au-delà de votre mémoire allouée (même avec le rembourrage) et vous arroserez l'arène de la mémoire.

Ce que vous devriez probablement est:

lstHeader = realloc (lstHeader, sizeof(Header) * (i+1)); 

Cela fera en sorte que vous avez suffisamment d'espace pour les éléments nécessaires Header dans votre allocation de mémoire. La raison pour laquelle c'est i+1 est parce que l'allocation initiale doit avoir un élément même si i est zéro.