Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.76/21: Рейтинг темы: голосов - 21, средняя оценка - 4.76
 Аватар для Avaddon74
571 / 353 / 133
Регистрация: 15.09.2017
Сообщений: 1,239

Стек вызовов

03.02.2018, 12:18. Показов 4427. Ответов 15
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Прочитал про то, что память не очищается после очистки стека от функции и просто освобождается. Логично предположил, что можно получить доступ к этой памяти и данным которые там лежат, набросал небольшой код:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
 
void func1() {
    int a[1] = { 200 };
    std::cout << &a[0] << ": " << a[0] << std::endl;
}
 
void func2() {
    int a[1];
    std::cout << &a[0] << ": " << a[0] << std::endl;
}
 
int main(){
    func1();
    func2();
}
Т.е. первая функция помещается в стек и объявляет и инициализирует массив, потом стек освобождается в него же помещается вторая функция и создает такой же массив, но не инициализирует его, после чего я пытаюсь получить значение.
По факту, указатели ссылаются на ту же ячейку памяти, но значение мусор. Т.е. значение перезаписалось?

Что я не правильно понял? И что я не так делаю?
Заранее спасибо!

Добавлено через 16 минут
то же самое и с динамической памятью:
C++
1
2
3
4
5
int *a = new int(200);
std::cout << a << ": " << *a << std::endl;
delete a;
a = new int;
std::cout << a << ": " << *a << std::endl;
0
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
03.02.2018, 12:18
Ответы с готовыми решениями:

Сколько адресов теоритически может содержать стек вызовов?
После какой по счету помещенной в стек функции возникает переполнение стека, и сколько автоматических переменных может в теории содержать...

Объяснить как работает рекурсивная функция и стек вызовов на моем примере
Объясните пожалуйста как работает рекурсивная функция и стек вызовов на моем примере. Здесь известный алгоритм &quot;Разделяй и...

Используя стек, описать функцию проверяющую, является ли стек пустым
Используя стек, описать функцию проверяющую, является ли стек пустым

15
277 / 226 / 93
Регистрация: 27.06.2016
Сообщений: 639
03.02.2018, 12:19
Avaddon74, C++ никаких вам гарантий на этот счёт, естественно, давать не будет, это вопрос того, как он реализован. У меня,к примеру, значения одинаковые получаются (g++-7, ubuntu, amd64). Скомпилируйте в ассемблерный код или дизассемблируйте объектный и посмотрите, что там происходит.
Цитата Сообщение от Avaddon74 Посмотреть сообщение
По факту, указатели ссылаются на ту же ячейку памяти
&a[0] точно одинаковый?
0
 Аватар для Avaddon74
571 / 353 / 133
Регистрация: 15.09.2017
Сообщений: 1,239
03.02.2018, 12:28  [ТС]
alex white, Использую VS2015
Вот что у меня выдает
Миниатюры
Стек вызовов  
0
 Аватар для Avaddon74
571 / 353 / 133
Регистрация: 15.09.2017
Сообщений: 1,239
03.02.2018, 12:29  [ТС]
Цитата Сообщение от alex white Посмотреть сообщение
Скомпилируйте в ассемблерный код или дизассемблируйте объектный и посмотрите, что там происходит
Не материтесь, я новичек )
0
277 / 226 / 93
Регистрация: 27.06.2016
Сообщений: 639
03.02.2018, 12:35
Avaddon74, попробуйте скомпилировать без каких либо отладочных опций, мб. код для отладки спец значения записывает в стек.
1
Неэпический
 Аватар для Croessmah
18149 / 10731 / 2067
Регистрация: 27.09.2012
Сообщений: 27,035
Записей в блоге: 1
03.02.2018, 12:51
Лучший ответ Сообщение было отмечено Avaddon74 как решение

Решение

Цитата Сообщение от Avaddon74 Посмотреть сообщение
Вот что у меня выдает
В Debug, да? А в Release переключите.
1
 Аватар для Avaddon74
571 / 353 / 133
Регистрация: 15.09.2017
Сообщений: 1,239
03.02.2018, 13:00  [ТС]
Croessmah, А что тогда происходит в дебаг режиме? Что-то дополнительно пишется в стек?

Кстати, а с динамической памятью данные разные
C++
1
2
3
4
5
6
int *a = new int(200);
    std::cout << a << ": " << *a << std::endl;
    delete a;
    a = new int;
    std::cout << a << ": " << *a << std::endl;
    return 0;
0
277 / 226 / 93
Регистрация: 27.06.2016
Сообщений: 639
03.02.2018, 13:09
Avaddon74, с динамической памятью всё также зависит на реализацию. Записывать значения просто так смысла особо нет (разве что при отладке, для облегчения идентификации висячих указателей), но система выделения/освобождения памяти (код, выполняющийся при new, delete), может записывать туда значения для своих собственных нужд, например производить разметку блоков и строить из них связные списки (то есть, записывать в блоки адреса следующих блоков).

Добавлено через 4 минуты
Avaddon74,
Например, у меня эта программа
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
#include <algorithm>
using namespace std;
 
template<typename T> void print(T first, T last)
{
    while(first != last)
        cout << *first++ << " ";
    cout << endl;
}
 
int main(){
    int *a = new int[10];
    std::fill(a,a+10,200);
    cout << a << ":\n";
    print(a,a+10);
    delete [] a;
    print(a,a+10);
    return 0;
}
пишет:
0x1c28c20:
200 200 200 200 200 200 200 200 200 200
0 0 200 200 200 200 200 200 200 200
1
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
03.02.2018, 16:23
Avaddon74,
Рассмотрим те случаи когда время жизни объектов может завершится до того как завершится выполнение самой программы.

Просто поймите следующее:
1. У каждого объекта расположенного в памяти есть время жизни (в зависимости от класса памяти у каждого объекта свое время жизни)
2. Для переменных созданных внутри функции время жизни ограничено закрывающей фигурной скобкой этой функции (то же самое в принципе относится и к другим конструкциям, у которых есть фигурные скобки).
3. Объекты созданные в динамической памяти живут до тех пор пока для их указателя не будет вызван delete

Использовать просроченные объекты нельзя, и если время жизни объекта истекло, это вовсе не означает что сами данные моментально должны быть уничтожены. Для уничтожения данных нужно выполнять доп. операции а это не выгодно. Проще просто перезаписать свободную область новыми данными если они будут.

Причем нет такого понятия как "уничтожить просроченные данные". В памяти всегда какие то данные есть, ну будут они например перезаписаны каким то мусором, и что? Только лишние операции будут что бы этот мусор туда забить.

Насчет адресов - не парьтесь.
Какие там выделяются адреса - вас особо заботить не должно, главное что бы одновременно используемые объекты не записывались по одному адресу Но опять же это не ваша забота.

По сути у вас на стек кладется 2 инта.
stack_pointer_addr = 1
push (stack_pointer_addr = 0)
pop (stack_pointer_addr = 1)
push (stack_pointer_addr = 0)

нет ничего удивительного эти int-ы были расположены по одному и тому же адресу...
0
 Аватар для Avaddon74
571 / 353 / 133
Регистрация: 15.09.2017
Сообщений: 1,239
03.02.2018, 17:18  [ТС]
Цитата Сообщение от Undisputed Посмотреть сообщение
Рассмотрим те случаи когда время жизни объектов может завершится до того как завершится выполнение самой программы.
Просто поймите следующее:
1. У каждого объекта расположенного в памяти есть время жизни (в зависимости от класса памяти у каждого объекта свое время жизни)
2. Для переменных созданных внутри функции время жизни ограничено закрывающей фигурной скобкой этой функции (то же самое в принципе относится и к другим конструкциям, у которых есть фигурные скобки).
3. Объекты созданные в динамической памяти живут до тех пор пока для их указателя не будет вызван delete
Это я знаю
Цитата Сообщение от Undisputed Посмотреть сообщение
Использовать просроченные объекты нельзя, и если время жизни объекта истекло, это вовсе не означает что сами данные моментально должны быть уничтожены. Для уничтожения данных нужно выполнять доп. операции а это не выгодно. Проще просто перезаписать свободную область новыми данными если они будут.
Причем нет такого понятия как "уничтожить просроченные данные". В памяти всегда какие то данные есть, ну будут они например перезаписаны каким то мусором, и что? Только лишние операции будут что бы этот мусор туда забить.
Это я тоже прекрасно понимаю, поэтому и хотел воспользоваться этим и посмотреть что лежит в памяти
Цитата Сообщение от Undisputed Посмотреть сообщение
Насчет адресов - не парьтесь.
Как это не парьтесь, я же должен понимать принцип работы, какой тогда из человека программист если на всё забивать?! Лучший специалист в своем деле тот, который знает всё изнутри и до мелочей!
Цитата Сообщение от Undisputed Посмотреть сообщение
По сути у вас на стек кладется 2 инта.
stack_pointer_addr = 1
push (stack_pointer_addr = 0)
pop (stack_pointer_addr = 1)
push (stack_pointer_addr = 0)
нет ничего удивительного эти int-ы были расположены по одному и тому же адресу...
Так я этого и добивался! И был поражен что результат разный когда ожидал одинаковый
В общем, лично вы, меня не поняли, но ответ я уже получил.

Добавлено через 4 минуты
Я сисадмин с 15-летним стажем и прекрасно понимаю, что когда удаляешь файл с диска, то данные файла остаются, а удаляется только ссылка на него из таблицы, этим то я и хотел воспользоваться только по отношению к памяти и всё, вот и был поражен что я не смог получить нужные данные.
0
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
03.02.2018, 17:18
Цитата Сообщение от Avaddon74 Посмотреть сообщение
Как это не парьтесь, я же должен понимать принцип работы, какой тогда из человека программист если на всё забивать?! Лучший специалист в своем деле тот, который знает всё изнутри и до мелочей!
Чем больше знаете - тем лучше
Я не в этом смысле
Просто как бы вы не переживали по этому поводу
Это не ваша задача. Компилятор сам должен генерить нужный код чтоб все лежало на своих местах и соответствовало стандарту и это все что вы вправе ожидать.

Детали реализации - implementation defined
В разных компиляторах может быть разный результат
Их задача просто соответствовать стандарту а не оправдание ваших ожиданий
1
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602
03.02.2018, 17:34
Цитата Сообщение от Avaddon74 Посмотреть сообщение
Т.е. первая функция помещается в стек и объявляет и инициализирует массив
Начнем с того, что пока функция ведет себя как будто массив инициализирован, компилятор может переделать ваш код в:
C++
1
std::cout << &a[0] << ": " << 200 << std::endl;//я точно знаю что a[0]==200, так что никто не заметит
Принцип "as if" - берем у пользователя чертежи бензинового автомобиля, ставим внутрь электрический двигатель и магнитофон с записью звука работающего ДВС. Едет как бензиновый? Гудит как бензиновый? Ну значит все по стандарту и нечего под капот лезть.
1
 Аватар для Avaddon74
571 / 353 / 133
Регистрация: 15.09.2017
Сообщений: 1,239
03.02.2018, 17:38  [ТС]
Цитата Сообщение от Renji Посмотреть сообщение
Принцип "as if" - берем у пользователя чертежи бензинового автомобиля, ставим внутрь электрический двигатель и магнитофон с записью звука работающего ДВС. Едет как бензиновый? Гудит как бензиновый? Ну значит все по стандарту и нечего под капот лезть.

Спасибо! Учту!
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9007 / 4708 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
03.02.2018, 22:48
Цитата Сообщение от Avaddon74 Посмотреть сообщение
Прочитал про то, что память не очищается после очистки стека от функции и просто освобождается.
Avaddon74, очищается желудок. Клизма так и называется, - "очистительная". Память - освобождается (тоже плохой термин). Лучше бы сказать деинициализируются объекты в этой памяти, но это не верно для встроенных типов. А для классов гарантирован вызов конструктора для каждого созданного объекта. Никто не знает когда в точности. Однако и это не значит что в память будут записаны нули или как-то ещё. Она просто помечается как свободная и (никто не знает когда, опять же) в неё могут быть записаны другие данные (которые затрут всё что было). Использовать локальные данные только-что умершего скоупа опасная затея, но в своей программе в качестве хака и на свой страх и риск... В общем, я бы не стал этого делать.

Добавлено через 4 часа 48 минут
Цитата Сообщение от IGPIGP Посмотреть сообщение
гарантирован вызов конструктора
деструктора конечно. И главное же перечитывал...
1
 Аватар для Avaddon74
571 / 353 / 133
Регистрация: 15.09.2017
Сообщений: 1,239
03.02.2018, 23:03  [ТС]
Цитата Сообщение от IGPIGP Посмотреть сообщение
деструктора конечно. И главное же перечитывал...
Я понял вас сразу Что вы опечатались
0
03.02.2018, 23:11

Не по теме:

Цитата Сообщение от Avaddon74 Посмотреть сообщение
Я понял вас сразу Что вы опечатались
Это приятно. :)
Я заметил поздновато, но решил отметить, так как читать будут может ещё. Avaddon74, тут (как и везде) случается, что кому-то захочется высказаться лет эдак через надцать. :D
Жаль только забыл что можно fake-овым сообщением помочь себе исправить.

0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
03.02.2018, 23:11
Помогаю со студенческими работами здесь

Программа добавляет введенный массив 5*5 в стек и выводит полученный стек двумя столбцами
Программа добавляет введенный массив 5*5 в стек и выводит полученный стек двумя столбцами #include &lt;iostream&gt; #include...

Заполнить стек 20 случайными числами с интервала [0; -10]. Вывести стек на экран. Изъять из стека каждый четвертый элеме
Заполнить стек 20 случайными числами с интервала . Вывести стек на экран. Изъять из стека каждый четвертый элемент, найти сумму изъятых...

Переменные в стеке. Где хранятся? Как обрабатываются? Есть ли программный стек или только стек процессора?
Есть у меня пробелы в познаниях, хотел бы их устранить. 1. Что такое стек в самом языке С++ ? 2. В какой памяти он хранится и почему...

Сформировать стек из 6 цифр. Вывести стек на экран. Удалить элементы из стека, увеличить каждый из них на единицу и снов
Сформировать стек из 6 цифр. Вывести стек на экран. Удалить элементы из стека, увеличить каждый из них на единицу и снова поместить в стек...

Сформировать стек из N чисел. Найти сумму нечетных чисел из стека. Результат поместить в стек
Здравствуйте. Помогите, пожалуйста, решить задачу: Сформировать стек из N чисел. Найти сумму нечетных чисел из стека. Результат поместить...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
16
Ответ Создать тему
Новые блоги и статьи
Автоматическое создание документа при проведении другого документа
Maks 29.03.2026
Реализация из решения ниже выполнена на нетиповых документах, разработанных в конфигурации КА2. Есть нетиповой документ "ЗаявкаНаРемонтСпецтехники" и нетиповой документ "ПланированиеСпецтехники". В. . .
Настройка движения справочника по регистру сведений
Maks 29.03.2026
Решение ниже реализовано на примере нетипового справочника "ТарифыМобильнойСвязи" разработанного в конфигурации КА2, с целью учета корпоративной мобильной связи в коммерческом предприятии. . . .
Автозаполнение реквизита при выборе элемента справочника
Maks 27.03.2026
Программный код из решения ниже на примере нетипового документа "ЗаявкаНаРемонтСпецтехники" разработанного в конфигурации КА2. При выборе "Спецтехники" (Тип Справочник. Спецтехника), заполняется. . .
Сумматор с применением элементов трёх состояний.
Hrethgir 26.03.2026
Тут. https:/ / fips. ru/ EGD/ ab3c85c8-836d-4866-871b-c2f0c5d77fbc Первый документ красиво выглядит, но без схемы. Это конечно не даёт никаких плюсов автору, но тем не менее. . . всё может быть. . .
Автозаполнение реквизитов при создании документа
Maks 26.03.2026
Программный код из решения ниже размещается в модуле объекта документа, в процедуре "ПриСозданииНаСервере". Алгоритм проверки заполнения реализован для исключения перезаписи значения реквизита,. . .
Команды формы и диалоговое окно
Maks 26.03.2026
1. Команда формы "ЗаполнитьЗапчасти". Программный код из решения ниже на примере нетипового документа "ЗаявкаНаРемонтСпецтехники" разработанного в конфигурации КА2. В качестве источника данных. . .
Кому нужен AOT?
DevAlt 26.03.2026
Решил сделать простой ланчер Написал заготовку: dotnet new console --aot -o UrlHandler var items = args. Split(":"); var tag = items; var id = items; var executable = args;. . .
Отправка уведомления на почту при создании или изменении элементов справочника
Maks 24.03.2026
Программная отправка письма электронной почты на примере типового справочника "Склады" в конфигурации БП3. Перед реализацией необходимо выполнить настройку системной учетной записи электронной. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru