как распределяется память для локальных переменных? - PullRequest
1 голос
/ 23 декабря 2011
int* pi;
{
    int ar[1000000];
    int a =3,b=4;
    ar[3]=a*b
    pi=ar;
}//ar is destroyed
int ar2[]={5,6,7,8,9};
char* f="zcxzsdaaaaaaaaa";
std::cout<<pi[3]<<std::endl;// prints 12

У меня есть 2 вопроса:

  1. Я слышал, что в стеке есть только указатели на данные. И если да, то где хранятся данные? Например, char* a="bbbb"; a - помещается в стек, "bbbb" - где-то еще. Где?

  2. Разве приведенный выше код не работает правильно, означает утечку памяти в 1000000 байт? Переменная ar уничтожена, но данные, на которые она указала, все еще существуют. И мы не можем использовать здесь удаление, поскольку ar не выделяется динамически.

Ответы [ 5 ]

4 голосов
/ 23 декабря 2011

Я слышал, что в стеке есть только указатели на данные

Вы ошиблись.Стек содержит фактические данные.Однако, если эти данные являются указателем, то это то, что хранится.

И если да, то где хранятся данные?Например, char * a = "bbbb";a - помещается в стек, "bbbb" - где-то еще.Где?

Да, a (указатель) хранится в стеке.Фактическая строка "bbbb" хранится в фиксированной части исполняемого файла.

Правильный ли приведенный выше код означает утечку памяти в размере 1000000 байт?Переменная ar уничтожена, но данные, на которые она указала, все еще существуют.И мы не можем использовать здесь удаление, так как ar не выделяется динамически.

Нет, существует разница между массивами и указателями на массивы.ar (все 1000000 байт) будет храниться в стеке.Это отличается от char const* ar = "... 1000000 chars ...";.Поскольку ar находится в стеке, оно будет автоматически "освобождено".

char const* a = "abcde"; // a is on the stack, pointing to "abcde" somewhere else.
char const b[6] = "abcde"; // *all* of b is on the stack, all 6 bytes

Проблема в вашем коде состоит в том, что pi указывает на что-то в стеке, которого больше нет.Это может произойти, когда вы запускаете код, потому что «освобождение» данных в стеке ничего не делает с данными в не отладочных сборках.Это не утечка памяти, у вас просто недопустимый указатель.

Последнее замечание: хотя практически все современные компьютерные архитектуры используют стек вызовов, стандарт C ++ не упоминает об этом.Обратите внимание, что люди часто говорят, что переменная «в стеке», но на самом деле она может просто существовать в регистре.Например, если вы скомпилировали свой код, переменная pi, вероятно, никогда не будет касаться стека, скорее всего, она просто останется в регистре на время действия функции, потому что обращение к стеку относительно дорого (по сравнению с регистрами).

3 голосов
/ 23 декабря 2011

ar также находится «в стеке». Технически вы можете получить к нему доступ, поскольку память все еще отображается в адресном пространстве (стек обычно отображается как единое целое) и видеть те же данные, что и ранее сохраненные, поскольку данные не были перезаписаны .

Это неопределенное поведение - вы можете прочитать перезаписанные данные, или ваша программа может аварийно завершить работу или произойти что-либо еще, включая воспринимаемую нормальную работу. Не полагайтесь на это поведение и не пытайтесь делать это в реальном коде (пробовать это в образовательных целях и спрашивать SO - это нормально).

Здесь нет утечки памяти - память стека автоматически восстанавливается при выходе из функции.

1 голос
/ 23 декабря 2011
  1. вы слышали неправильно.стек содержит данные

  2. нет, весь массив можно считать «уничтоженным», когда он выходит из области видимости

0 голосов
/ 23 декабря 2011

Не похоже, что проблема утечки памяти действительно решена. В C ++ для самостоятельного выделения памяти вы используете ключевое слово new или malloc , и именно здесь возникает проблема с утечкой памяти. Язык разработан так, что все пространство памяти локальных переменных освобождается, как только оно выходит из области видимости. Как все указали, ar находится в локальной области pi {}, поэтому после его выхода эти области памяти можно использовать повторно или легко перезаписать, поэтому, если бы вы напечатали результаты pi позже в коде, манипулируя стеком, как вы были в этой {} области видимости, чем пи может иметь другое значение

0 голосов
/ 23 декабря 2011

1) Все переменные находятся в стеке.Вы не выделяете память самостоятельно.

2) Нет утечки памяти.Вся переменная находится в стеке и уничтожается при выходе из области видимости переменной.Вы ничего не выделяете с помощью new.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...