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

Стек вызовов

03.02.2018, 12:18. Показов 4371. Ответов 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
18144 / 10728 / 2066
Регистрация: 27.09.2012
Сообщений: 27,026
Записей в блоге: 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
9005 / 4706 / 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
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru