2010-12-10 5 views
3

On dit que la variable locale sera allouée et désallouée automatiquement lorsque la fonction se termine en C/C++. Selon ma compréhension, une fois désallouée, la valeur détenue par la variable locale sera également détruite !!! S'il vous plaît me corriger si je me trompeAllocation de mémoire de pile

Tenir compte du code ci-dessous:

void doSomething(int** num) 
{ 
    int a = 10; 
    *num = &a; 
} // end of function and a will be destroyed 

void main() 
{ 
    int* number; 
    doSomething(&number); 
    cout << *number << endl; // print 10 ??? 
} 

Quelqu'un pourrait me préciser?

+4

Ugh, s'il vous plaît ne pas fais 'void main()'. – birryree

+0

Avez-vous essayé de l'exécuter? – Josh

+3

Il imprime '10' uniquement parce que la valeur n'a pas encore été écrasée par quelque chose d'autre. C'est seulement à cause de la chance que cela semble fonctionner. – Gabe

Répondre

8

Vous avez raison. votre cout peut ou non imprimer 10. Il va invoquer un comportement indéfini. Pour faire un peu plus d'une note, essayez d'exécuter le code suivant sous votre compilateur sans optimisations activées.

#include <iostream> 
using namespace std; 

void doSomething(int** num) 
{ 
    int a = 10; 
    *num = &a; 
} 

void doSomethingElse() { 
    int x = 20; 
} 

int main() 
{ 
    int* number; 
    doSomething(&number); 
    doSomethingElse(); 
    cout << *number << endl; // This will probably print 20! 
} 
+0

Je pense que l'utilisateur538042 obtient 10, c'est pourquoi le message a été fait. –

+0

+1, bien que le 'cout' puisse en fait imprimer 10. Ou il peut imprimer -34528719849, formater le disque dur ou invoquer les démons nasaux. – suszterpatt

+0

Je parierais que 'cout << * nombre << endl;' affiche toujours 10 s'il est appelé immédiatement après 'doSomething (& number);' et pas de multithreading impliqué. – a1ex07

5

Dans ce cas, le nombre entier a est sur la pile. Vous renvoyez l'adresse de cette variable au programme principal. La valeur à cet emplacement d'adresse après l'appel n'est pas définie. Il est possible dans certaines situations qu'il puisse imprimer 10 si cette partie de la pile n'était pas écrasée (mais vous ne voudriez certainement pas compter dessus).

1

Le contenu de la mémoire n'est pas réellement détruit. Dans ce cas, num pointera sur un emplacement qui n'est affecté à aucune variable, mais il conservera son contenu, qui a été défini sur 10.

1

La mémoire pointée sur a été renvoyée au système . Cela signifie qu'il conservera n'importe quelle valeur jusqu'à ce que le système affecte ce bloc de mémoire à une autre variable et qu'il soit surchargé avec une valeur.

Les variables locales sont libérées lorsqu'elles sortent de la portée. Si vous essayez de retourner une valeur à l'aide d'un paramètre sur une fonction:

void doSomething(int** num) 
{ 
    int* a = new int; 
    *a = 10; 
    *num = a; 
} 

int main() 
{ 
    int* number = 0; 
    doSomething(&number); 
    std::cout << *number << std::endl; // print 10 ??? 
    if (number) delete number; 
} 

Bien que, pour quelque chose ce simple, vous êtes mieux de faire ceci:

int doSomething() 
{ 
    return 10; 
} 

int main() 
{ 
    std::cout << doSomething() << std::endl; 
} 
+0

@Zac: "Bleurgh!" dirigé sur le premier exemple, pour ma part. Est-ce vraiment une si bonne idée d'inculquer aux débutants les merveilles de l'allocation de la mémoire et de compter sur l'appelant pour le relancer? :) Pour l'OP - lire Effective C++, je me souviens de l'avoir un bon point sur ce point particulier. De plus c'est juste un bon livre quand même. –

+0

@Zac, intéressant, vous vérifiez avant de supprimer mais pas avant de-référencement! – Nim

+0

@Stuart: C'était plus pour répondre à sa question. Il ne peut pas allouer un objet sur la pile et renvoyer l'emplacement de mémoire de cet élément et le rendre valide. D'où la raison du second exemple. –