2010-03-25 4 views
11

La mémoire allouée avec malloc ne persiste pas en dehors de la portée de la fonction?

Salut,

Je suis un peu nouveau pour la fonction malloc C, mais de ce que je sais qu'il doit stocker la valeur dans le tas, de sorte que vous pouvez référencer avec un pointeur de l'extérieur du champ d'origine . J'ai créé un programme de test qui est censé faire cela mais je continue à obtenir la valeur 0, après l'exécution du programme. Qu'est-ce que je fais mal?

int f1(int * b) { 
b = malloc(sizeof(int)); 
*b = 5; 
} 

int main() { 
int * a; 
f1(a); 
printf("%d\n", a); 
return 0; 
} 

Répondre

6

La mémoire elle-même persiste, mais il fuit parce que vous ne fournissez pas le pointeur alloué à l'appelant. En outre, vous imprimez a lorsque vous devez imprimer *a. Enfin, vous ne renvoyez pas un int de f1.

Essayez:

void f1(int **b) { 
*b = malloc(sizeof(int)); 
**b = 5; 
} 

int main() { 
int *a; 
f1(&a); 
printf("%d\n", *a); 
free(a); 
return 0; 
} 
0

Votre problème est en fait rien à voir avec malloc, mais plutôt le fait que vous passez la valeur du pointeur occupe actuellement, plutôt que l'adresse de celui-ci. Effectuez les opérations suivantes:

int f1(int ** b) { 
    *b = malloc(sizeof(int)); 
    **b = 5; 
} 

int main() { 
    int * a; 
    f1(&a); 
    printf("%d\n", *a); 
    return 0; 
} 

En passant la valeur de pointeur que vous étiez, il n'y avait aucun moyen pour la valeur créée malloc pour être stocké dans le pointeur.

+3

Ceci est de nouveau passé en valeur. Passer l'adresse d'une valeur par. ** Il n'y a pas de laissez-passer par référence en C ** – raj

+0

Assez juste. Mise à jour pour être plus précis dans C. – Dusty

0

L'adresse int *b est supprimée lorsque la fonction renvoie. Pour l'enregistrer, vous devez utiliser un pointeur d'un pointeur

int f1(int ** b) { 
    *b = malloc(sizeof(int)); 
    **b = 5; 
} 
8

On dirait que vous êtes mal compris une partie fondamentale de la façon dont fonctionne C - à savoir qu'il est une langue « passage par valeur » . Afin que main() connaisse la mémoire que vous avez allouée, vous devez la récupérer. Le code suivant vous fera ce que vous voulez:

int f1(int **b) 
{ 
    *b = malloc(sizeof(int)); 
    **b = 5; 
} 

int main(int argc, char **argv) 
{ 
    int *a; 
    f1(&a); 
    printf("%d\n", *a); 
    return 0; 
} 

Il existe quelques différences entre ce code et le vôtre; d'abord, la signature de f1() a changé, de sorte qu'il peut retourner le résultat de l'appel malloc() dans le pointeur passé. Ensuite, l'appel à f1() a été changé pour passer l'adresse de a plutôt que a lui-même - important si vous voulez qu'il soit «rempli» par f1(), pour ainsi dire. Enfin, le printf() dans main() a été modifié pour imprimer la valeur pointée plutôt que le pointeur lui-même.

+7

Je ne sais pas pourquoi tout le monde a sauté directement à l'aide d'un pointeur-à-un-pointeur - ce n'est pas la meilleure façon d'expliquer à quelqu'un qui a des problèmes avec partie fondamentale de la langue. Pourquoi ne pas simplement retourner le pointeur de 'f1()'? – caf

+0

@caf, oui! c'est simple pour un débutant à comprendre.! – raj

+0

Merci beaucoup pour vos commentaires à tous! Mon code fonctionne maintenant. Je ne peux pas avoir la fonction retourner le pointeur, parce que la fonction dans mon projet actuel, il est déjà en train de retourner quelque chose d'autre .. Merci encore! –

22

Oui! a est passé par valeur de sorte que le pointeur b en fonction f1 sera locale .. soit retourner b,

int *f1() { 
    int * b = malloc(sizeof(int)); 
    *b = 5; 
    return b; 
} 

int main() { 
    int * a; 
    a = f1(); 
    printf("%d\n", *a); 
    // keep it clean : 
    free(a); 
    return 0; 
} 

ou passer l » adresse a

int f1(int ** b) { 
    *b = malloc(sizeof(int)); 
    **b = 5; 
} 

int main() { 
    int * a; 
    f1(&a); 
    printf("%d\n", *a); 
    // keep it clean : 
    free(a); 
    return 0; 
} 
5

laisse supposer que vous attribuez une valeur de NULL à un avant d'appeler la fonction f1.Maintenant la façon dont f1 est définie prend son argument (pointeur vers un int) par valeur. C'est b sera une autre variable de type int * qui sera un copie de a. Donc, b aura également une valeur de NULL. Maintenant dans f1 vous modifiez la valeur par b en lui affectant l'adresse de mémoire allouée dynamiquement en utilisant malloc. Disons que l'adresse mémoire est 0x123. À la suite de cette affectation, b a changé sa valeur de NULL à 0x123 mais a (dans main) continue à contenir NULL, car le changement b ne changera pas a, car ils sont deux variables distinctes. À la suite de cela, lorsque vous revenez de la fonction f1 un restera inchangé.

Il existe 2 façons de résoudre ce problème. Un, vous pouvez rendre la fonction f1 retourner la valeur de la b changé puis l'assigner à un main et deux, vous pouvez passer l'une par adresse afin que toutes les modifications apportées dans f1 affecteront un main aussi.

// f1 now returns the value of b. 
int* f1() { 
int *b = malloc(sizeof(int)); 
*b = 5; 
return b; 
} 

int main() { 
int *a = NULL; 
a = f1(); // assign the return value of f1 to a. 
printf("%d\n", *a); // prints 5...not its *a not just a. 
return 0; 
} 

.

// f1 now takes the address of a. 
void f1(int **b) { 
*b = malloc(sizeof(int)); // you are actually altering a indirectly. 
**b = 5; 
} 

int main() { 
int *a = NULL; 
f1(&a); // now pass the address of a to f1. 
printf("%d\n", *a); // prints 5...not its *a not just a. 
return 0; 
} 
Questions connexes