2010-12-10 8 views
3

Говорят, что локальная переменная будет выделена и освобождена автоматически, когда функция закончится на C/C++.Распределение памяти в стеке

Согласно моему пониманию, когда оно было освобождено, значение, удерживаемое локальной переменной, также будет уничтожено !!! Пожалуйста, поправьте меня, если я ошибаюсь

Рассмотрим следующий код:

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 ??? 
} 

Может кто-нибудь прояснить для меня?

+4

Тьфу, пожалуйста, не do 'void main()'. – birryree

+0

Вы попробовали запустить его? – Josh

+3

Он печатает '10' только потому, что значение еще не было перезаписано чем-то еще. Только из-за удачи, похоже, он работает. – Gabe

ответ

8

Вы верны. ваш cout может или не может печатать 10. Он будет вызывать неопределенное поведение.


Чтобы сделать немного больше примечания, попробуйте запустить следующий код под своим компилятором без включения оптимизации.

#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

Я думаю, что пользователь538042 получает 10, поэтому пост был сделан. –

+0

+1, хотя 'cout' может на самом деле распечатать 10. Или он может печатать -34528719849, отформатировать жесткий диск или вызвать носовых демонов. – suszterpatt

+0

Я бы поспорил, что 'cout << * number << endl;' всегда печатает 10, если он вызывается сразу после 'doSomething (& number);' и не задействовано многопоточность. – a1ex07

5

В этом случае целое число a находится в стеке. Вы возвращаете адрес этой переменной в основную программу. Значение в этом адресе после вызова не определено. В некоторых ситуациях можно напечатать 10, если эта часть стека не была перезаписана (но вы, конечно, не хотели бы полагаться на нее).

1

Содержимое памяти фактически не уничтожено. Для этого случая num укажет на местоположение, которое не выделяется для какой-либо переменной, но оно будет содержать его содержимое, которое было установлено на 10.

1

Описанная память была возвращена обратно в систему , Это означает, что он сохранит любое значение, которое оно имело до тех пор, пока система не назначит этот блок памяти другой переменной, и она будет переопределена значением.

Локальные переменные освобождаются при выходе из сферы действия. Если вы пытаетесь вернуть значение с помощью из параметра в функции:

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; 
} 

Хотя, для чего-то это просто, вам лучше всего сделать это:

int doSomething() 
{ 
    return 10; 
} 

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

@ Zac: "Bleurgh!" направленный на первый пример, с моей стороны. Неужели это такая замечательная идея внедрить новичков с чудесами выделения памяти и полагаться на вызывающего, чтобы освободить его снова? :) К OP - читайте Эффективный C++, я, кажется, помню, что у него хороший предмет в этом конкретном пункте. В любом случае, это хорошая книга. –

+0

@Zac, интересно, вы проверяете перед удалением, но не перед де-ссылкой! – Nim

+0

@Stuart: Это было больше, чтобы ответить на его вопрос. Он не может выделить элемент в стеке и передать ячейку памяти этого элемента обратно и сделать ее действительной. Отсюда и причина второго примера. –