2010-09-24 5 views
1

pourquoi le code ci-dessous me donne l'erreur de "double free ou corruption" ... quand je compile et exécute avec gcc [(Debian 4.4.4-8) 4.4.5 20100728 (prédémarrage)]. Merci d'avance!ansi c struct {avec tableau dynamique} assigné à array qui est realloc

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

typedef struct 
{ 
int *index1; 
} data; 

void doo(int *); 

int main(int argc, char *argv[]) 
{ 
int *a = (int *) malloc(10*sizeof(int)); 
int i; 

for(i=0; i<10; i++) 
{ 
    a[i] = 2*i; 
} 

doo(a); 

data one; 
one.index1 = a; 

printf("%d\n", one.index1[4]); 

free(a); 

printf("%d\n", one.index1[4]); 

free(one.index1); 
return 0; 
} 

void doo(int *b) 
{ 
b = (int *) realloc(b, 5*sizeof(int)); 
return; 
} 
+0

est ce devoirs btw? –

+0

si vous avez 2 questions à faire, commencez 2 messages. Ne réutilisez pas un message pour faire une autre question. ** Bienvenue à SO, amusez-vous! ** – pmg

Répondre

1
one.index1=a; 
... 
free(a); 
... 
free(one.index1); 
... 

Ergo, le double libre.

void doo(int *b) 
{ 
b = (int *) realloc(b, 5*sizeof(int)); 
return; 
} 

Lorsque vous passez le pointeur à cette fonction, sa valeur (qui est enfait une adresse), est copiée dans b, un autre pointeur int local. Maintenant, lorsque vous réalisez un espace pour 5 ints, il change l'allocation d'espace pour un infact. Ainsi, votre espace est réduit de 10 à 5 pouces.

Comme demandé par OP, pour obtenir les mêmes données pointeurs de mémoire &, espace doit être alloué à nouveau pour le nouveau pointeur, comme un pointeur est après tout, juste une variable, en maintenant une adresse. Si vous allouez deux blocs séparés, vous obtiendrez deux adresses distinctes, qui peuvent être libérées individuellement.

+0

Comment puis-je obtenir une copie de "a" stocké dans "one.index1 "pas le pointeur? – jkl

+0

a a une adresse. Cette adresse est copiée dans one.index1. Donc, maintenant les deux ont la même adresse. Si vous effectuez un free() sur un, l'espace alloué à partir de cette adresse est libéré. Si vous essayez de libérer à nouveau le même espace, vous rencontrerez une erreur. –

+0

Donc, y a-t-il une façon de le dire pour cloner "a", et assigner ce clone à "one.index1"? Alors que "un" et "one.index1" auront les mêmes données, mais un pointeur de mémoire séparé. – jkl

1

Parce que le stockage pointé par « a » et « one.index1 » sont les mêmes (affectation avant la première printf). Ainsi vous avez un double gratuit.

+0

Comment puis-je obtenir une copie de "a" stocké dans "one.index1" pas le pointeur? – jkl

0

Vous passez à faire un pointeur. Vous modifiez le pointeur lui-même, mais votre fonction principale n'obtient pas la nouvelle adresse.

+0

Pas la raison pour le "double gratuit", mais vaut la peine de corriger – pmg

+0

Comment puis-je obtenir une copie de "a" stocké dans "one.index1" pas le pointeur? – jkl

+0

@pmg, OP réduit l'espace mémoire alloué. Pourquoi cela causerait-il une relocalisation ou un changement d'adresse? –

0

Cela se produit parce que vous faites one.index1 et a pointent vers le même emplacement de mémoire.

Pour tester cette ajouter ce qui suit à votre code:

one.index1 = a; // from now on, both variables point to the same address 

printf("-> 0x%x\n", one.index1); 
printf("-> 0x%x\n", a); 

printf("%d\n", one.index1[4]); 

free(a); // release the resource pointed by a 

// You should not try to print the data of one.index1[4] since 
// that piece of memory doesn't exist no more. 
printf("%d\n", one.index1[4]); 

free(one.index1); // Problem: trying to free the same memory resource TWICE. 

Vous remarquerez que les deux pointeurs impriment les mêmes adresses de mémoire. Donc, après l'exécution de free(a);, exécuter free(one.index1); est redondant, et essayer de libérer une ressource qui n'est plus allouée est ce qui cause le problème.

+0

Vous ne pouvez pas imprimer une adresse avec le spécificateur de format "% x" et attendre une sortie raisonnable sur tous les systèmes.Utilisez le spécificateur de format "% p" et convertissez l'adresse en 'void *' * (et ne vous attendez pas à une sortie raisonnable sur tous les systèmes) *. – pmg

+1

@pmg Merci. Vous pouvez l'imprimer comme vous voulez. – karlphillip