Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 5.00/16: Рейтинг темы: голосов - 16, средняя оценка - 5.00
Chelioss
185 / 185 / 21
Регистрация: 08.01.2011
Сообщений: 1,139
1

Как это работает?

28.09.2011, 17:57. Просмотров 2948. Ответов 24
Метки нет (Все метки)

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
int *fun()
{
    int a = 5;
    return &a;
}
int main()
{
        int *ptr = fun();
        std::cout << *ptr;
        system( "pause" );
        return 0;
}
Как я это себе представляю: функция fun возвращает адрес автоматической переменной. Но эта переменная при завершении работы функции fun уничтожается, поэтому указатель ptr указывает на недействительную память.
Даже компилятор выдает это :warning C4172: возвращение адреса локальной или временной переменной

Так почему это работает?
0
QA
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
28.09.2011, 17:57
Ответы с готовыми решениями:

Как это работает? Я хочу спросить как работает C++ и где можно про него почитать
Привет, котоны. Заранее благодарю. Это будет моих общих вопросов нить, т.к. создавать целую ветку...

Русификация.Работает-супер! Обьяснитте, как это работает?
#include &lt;iostream&gt; #include &lt;conio.h&gt; #include &lt;windows.h&gt; using namespace std; char*...

Как это работает?
#include &lt;iostream&gt; #include &lt;cstring&gt; using namespace std; int main() { char* s=new...

Как это работает
Здравствуйте уважаемые форумчане!Как это работает? Как например предотвратить выход за приделы...

Как это работает?
Здравствуйте, можете, пожалуйста, поэтапно объяснить как работает приведенный ниже фрагмент кода?...

24
nxnx
Формучанин
362 / 293 / 41
Регистрация: 02.11.2010
Сообщений: 1,234
28.09.2011, 17:59 2
Цитата Сообщение от Chelioss Посмотреть сообщение
Так почему это работает?
где написано что запрещено возвращать неправильный адрес?
если выводит правильное значение-это совпадение.
Для более подробной информации нужно прогнать в отладчике и глянуть как меняется стек.
1
Chelioss
185 / 185 / 21
Регистрация: 08.01.2011
Сообщений: 1,139
28.09.2011, 18:05  [ТС] 3
Я не про возвращение адреса говорю.
Почему выводится число 5?

Добавлено через 1 минуту
Цитата Сообщение от nxnx Посмотреть сообщение
если выводит правильное значение-это совпадение.
Поменял несколько раз значение, которым специализируется переменная a и все время выводит правильно.

Добавлено через 1 минуту
Похоже я понял, почему работает. Переменная уничтожается, но та область памяти, в которой хранилась значение 5, остается не измененной, т.е. в ней по прежнему находится набор битов соответствующей цифре 5.

Я думал, что доступ возможен только к той памяти, которая выделяется программой, но оказывается можно спокойно работать со всей доступной памятью. Хотя я наверно не совсем правильно говорю.
0
nxnx
Формучанин
362 / 293 / 41
Регистрация: 02.11.2010
Сообщений: 1,234
28.09.2011, 18:11 4
чтобы лучше понять, можно попробовать собрать такой код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
#include <cstdlib>
int *fun()
{
        int a = 5;
        return &a;
}
int fun2()
{
    int b=10;
    return b*0;
}
int main()
{
       
    int *ptr = fun();
    fun2();
    std::cout << *ptr<<"\n";
    system( "pause" );
       
        return 0;
}
и желательно с выключенной оптимизацией. Для понимания- прогнать через отладчик.
1
28.09.2011, 18:11
ISergey
Maniac
Эксперт С++
1438 / 942 / 156
Регистрация: 02.01.2009
Сообщений: 2,803
Записей в блоге: 1
28.09.2011, 18:11 5
Цитата Сообщение от Chelioss Посмотреть сообщение
Похоже я понял, почему работает. Переменная уничтожается, но та область памяти, в которой хранилась значение 5, остается не измененной, т.е. в ней по прежнему находится набор битов соответствующей цифре 5.
Должно быть так...
но компилятор по хитрому сделал))
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
int *fun()
{
    int a = 5;
    return &a;
}
int main()
{
    int *ptr = fun();
    std::cout << *ptr;
00401000 8B 0D 48 20 40 00    mov         ecx,dword ptr [__imp_std::cout (402048h)]  
00401006 6A 05                push        5  ; !
00401008 FF 15 44 20 40 00    call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (402044h)]  
    system( "pause" );
0040100E 68 F4 20 40 00       push        offset string "pause" (4020F4h)  
00401013 FF 15 A8 20 40 00    call        dword ptr [__imp__system (4020A8h)]  
00401019 83 C4 04             add         esp,4  
    return 0;
0040101C 33 C0                xor         eax,eax  
}
0040101E C3                   ret
Проще говоря код так переделал..
C++
1
std::cout << 5 ;
1
DKOI
24 / 24 / 0
Регистрация: 08.09.2010
Сообщений: 136
28.09.2011, 18:17 6
Даже если компилятор бы так не веселился, оно бы "работало". Шутка в том, что область памяти освобождается, но не перезаписывается тут же. В ней лежит все тот же элемент, хоть ячейка и отдана уже в пул. Её можно использовать, но никто не гарантирует, что в какой-то определенный момент времени она не будет снова выделена.
1
Chelioss
185 / 185 / 21
Регистрация: 08.01.2011
Сообщений: 1,139
28.09.2011, 18:18  [ТС] 7
Т.е. я правильно понял и мое утверждение верно.
0
ISergey
Maniac
Эксперт С++
1438 / 942 / 156
Регистрация: 02.01.2009
Сообщений: 2,803
Записей в блоге: 1
28.09.2011, 18:23 8
Переменная в стеке должна лежать.. так как стек не затерся она целой осталась..
Если включить отладочный режим оно так и будет..
1
LosAngeles
Заблокирован
28.09.2011, 18:24 9
Цитата Сообщение от DKOI Посмотреть сообщение
хоть ячейка и отдана уже в пул
ни в какой пул никакая ячейка не была отдана, это стек
1
DKOI
24 / 24 / 0
Регистрация: 08.09.2010
Сообщений: 136
28.09.2011, 18:29 10
Цитата Сообщение от LosAngeles Посмотреть сообщение
ни в какой пул никакая ячейка не была отдана, это стек
Говоря пул, я не подразумеваю системный пул памяти, а подразумеваю, что адрес памяти уже не "привязан" и может снова быть "выделен". Извиняюсь за терминологию, если вам не нравится такое использование.
1
Chelioss
185 / 185 / 21
Регистрация: 08.01.2011
Сообщений: 1,139
28.09.2011, 18:34  [ТС] 11
Цитата Сообщение от ISergey Посмотреть сообщение
Переменная в стеке должна лежать.. так как стек не затерся она целой осталась..
Если включить отладочный режим оно так и будет..
Не понял. После окончании работы функции, "функция выталкивается из вершины стэка"
и память, отведенная автоматическим переменным, освобождается, но не изменяется.
Я так и не понял причем тут стэк, если дело в памяти.
DKOI я думаю, сказал более правильно.
0
DKOI
24 / 24 / 0
Регистрация: 08.09.2010
Сообщений: 136
28.09.2011, 18:36 12
Локальные переменные функции хранятся в стеке.
1
ISergey
Maniac
Эксперт С++
1438 / 942 / 156
Регистрация: 02.01.2009
Сообщений: 2,803
Записей в блоге: 1
28.09.2011, 18:38 13
Chelioss, http://asmworld.ru/uchebnyj-kurs/026-lokalnye-peremennye/
1
Chelioss
185 / 185 / 21
Регистрация: 08.01.2011
Сообщений: 1,139
28.09.2011, 18:38  [ТС] 14
Цитата Сообщение от DKOI Посмотреть сообщение
Локальные переменные функции хранятся в стеке.
А стэк хранится в единой памяти, отведенной системой для программы, разве не так?
0
DKOI
24 / 24 / 0
Регистрация: 08.09.2010
Сообщений: 136
28.09.2011, 18:40 15
Цитата Сообщение от Chelioss Посмотреть сообщение
А стэк хранится в единой памяти, отведенной системой для программы, разве не так?
Так то оно так, но не совсем. Для системы, стек процесса - несколько отличная от кучи или сегмента данных структура.
1
nxnx
Формучанин
362 / 293 / 41
Регистрация: 02.11.2010
Сообщений: 1,234
28.09.2011, 18:43 16
стек это отдельная страница памяти, которая выделяется при запуске программы.
регистр esp указывает на вершину стека.
1
Chelioss
185 / 185 / 21
Регистрация: 08.01.2011
Сообщений: 1,139
28.09.2011, 18:44  [ТС] 17
Ответ на мой вопрос в первом посте:
При уничтожении переменной, память освобождается от привязки, но не изменяется. С чужой памятью можно работать.( памятью, отведенной системы для программы)
0
OstapBender
587 / 525 / 76
Регистрация: 22.03.2011
Сообщений: 1,585
28.09.2011, 18:46 18
да UB тут и всё.
так вышло случайно.

да и вы сами написали
Цитата Сообщение от Chelioss Посмотреть сообщение
При уничтожении переменной, память освобождается от привязки, но не изменяется. С чужой памятью можно работать.( памятью, отведенной системы для программы)
1
Chelioss
185 / 185 / 21
Регистрация: 08.01.2011
Сообщений: 1,139
28.09.2011, 18:47  [ТС] 19
Цитата Сообщение от OstapBender Посмотреть сообщение
да UB тут и всё.
так вышло случайно.
Что такое UB?
0
DKOI
24 / 24 / 0
Регистрация: 08.09.2010
Сообщений: 136
28.09.2011, 18:49 20
Цитата Сообщение от Chelioss Посмотреть сообщение
Что такое UB?
Недокументированная особенность.
1
28.09.2011, 18:49
Answers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
28.09.2011, 18:49

Как это работает?
Читаю я кое какой &quot;учебник&quot;, и в нём появился такой вот кусок кода int input (tank&amp; t, char map)...

Как это работает?
Доброго времени суток. Граждане программисты, подскажите пожалуйста как работает данный кусок...

Как это работает?
Не могу понять, как это работает: #include &lt;iostream&gt; using namespace std; int main() { ...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.