С Новым годом! Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.79/29: Рейтинг темы: голосов - 29, средняя оценка - 4.79
56 / 52 / 21
Регистрация: 01.01.2012
Сообщений: 347
1

В какой области памяти лежат объекты?

11.09.2017, 22:03. Показов 5950. Ответов 61
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Здрст.

C++
1
2
3
4
5
6
7
8
struct H
{
    int a;
};
int main()
{
    H *p = new H;
}
объект по адресу p лежит в куче.
Вопрос: а где лежит объект-член 'a'? (в куче или в стеке)
и с помощью какого средства можно это проверить?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
11.09.2017, 22:03
Ответы с готовыми решениями:

В какой области памяти хранится указатель (сама переменная, которая хранит адрес)?
Привет! В общем у меня возник небольшой вопрос :) Если мы объявляем указатель, выделяем ему...

Вопрпос про const: в какой области памяти они находятся, и где это объявлять ?
Приветствую. У меня вот такая задача - завести массив констант, причём он используется ТОЛЬКО...

Считается ли хорошим тоном создавать объекты классов в области глобальных переменных
Считается ли хорошим тоном создавать объекты классов в области глобальных переменных? class FX...

Перераспределение памяти с new под объекты
есть класс #include <iostream> #include <string> using namespace std; class tel_book {...

61
Модератор
Эксперт по электронике
8950 / 6716 / 921
Регистрация: 14.02.2011
Сообщений: 23,706
12.09.2017, 21:26 21
Author24 — интернет-сервис помощи студентам
Цитата Сообщение от Captain Maxee Посмотреть сообщение
Так-то память для нее выделена на #1, но область ее видимости начинается только с #2,
не факт
в последнее время очень плотно сижу с микроконтроллерами
а там с памятью напряженка, а вот регистров очень многотак что локальные переменные очень часто запихиваются в регистр
причем может запихать в регистр который до этого использовала другая переменная
вполне возможен вариант когда область видимости равна "выделению памяти"
2
Неэпический
18109 / 10696 / 2062
Регистрация: 27.09.2012
Сообщений: 26,933
Записей в блоге: 1
12.09.2017, 21:44 22
hoggy, время жизни объекта у нас начинается когда?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>
 
 
struct Test
{ 
    Test() {
        std::cout << "ctor" << std::endl;
    } 
};
 
 
void foo(bool x)
{
    static Test t1;
    if (x) {
        static Test t2;
    }
}
 
 
int main()
{
    std::cout << "1:\n";
    foo(false);
    std::cout << "2:\n";
    foo(true);
}
Цитата Сообщение от Notoriously Посмотреть сообщение
Допустим Эккель пишет, что память для всех переменных блока выделяется сразу при заходе в него.
Память для стека выделяется при старте процесса/потока.
Затем всё выделение на стеке сводится к работе с регистрами.
Если компилятор может посчитать сколько необходимо
памяти и выделить её на стеке одним махом, то почему нет?
Если же компилятор не может этого посчитать?
Проще всего такое продемонстрировать на C,
либо на C++ с VLA от GCC:
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <stdio.h>
#include <stdlib.h>
 
void foo(int x, int y)
{
    char str[1024];
    scanf("%s", str);
    printf("%s", str);
    if( rand() ) {
       char buffer[x + y];
       scanf("%s", buffer);
       printf("block1: %s", buffer);
    } else {
       char buffer[y - x];
       scanf("%s", buffer);
       printf("block2: %s", buffer);
    }
}
 
 
 
int main(void)
{
    foo(1024, 2048);
}
Смотрим код foo в asm (смотрел с -O3):
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
foo(int, int):
  push rbp
  xor eax, eax
  mov rbp, rsp
  push r13
  push r12
  push rbx
  mov ebx, esi
  lea rsi, [rbp-1056]
  mov r13d, edi
  mov edi, OFFSET FLAT:.LC0
  sub rsp, 1032 ;<--РАЗ ВЫДЕЛЕНИЕ
  call scanf
  lea rsi, [rbp-1056]
  mov edi, OFFSET FLAT:.LC0
  xor eax, eax
  mov r12, rsp
  call printf
  call rand
  test eax, eax
  jne .L6
  sub ebx, r13d
  mov edi, OFFSET FLAT:.LC0
  xor eax, eax
  movsx rbx, ebx
  add rbx, 15
  and rbx, -16
  sub rsp, rbx ;<--ДВА ВЫДЕЛЕНИЕ
  mov rsi, rsp
  call scanf
  mov rsi, rsp
  mov edi, OFFSET FLAT:.LC2
  xor eax, eax
  call printf
  mov rsp, r12
  lea rsp, [rbp-24]
  pop rbx
  pop r12
  pop r13
  pop rbp
  ret
.L6:
  add ebx, r13d
  mov edi, OFFSET FLAT:.LC0
  xor eax, eax
  movsx rbx, ebx
  add rbx, 15
  and rbx, -16
  sub rsp, rbx  ;<--ТРИ ВЫДЕЛЕНИЕ
  mov rsi, rsp
  call scanf
  mov rsi, rsp
  mov edi, OFFSET FLAT:.LC1
  xor eax, eax
  call printf
  mov rsp, r12
  lea rsp, [rbp-24]
  pop rbx
  pop r12
  pop r13
  pop rbp
  ret
В общем случае стандарт не описывает что и когда должно выделяться.
А возьмем такой код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <stdio.h>
#include <stdlib.h>
 
void foo(int x)
{
    bool f = x;
    if(f) {
        char str[1024];
        scanf("%s", str);
        printf("%s", str);
    } else {
        char str[64];
        scanf("%s", str);
        printf("t: %s", str);
    }
}
 
 
int main()
{
    int x;
    scanf("%d", &x);
    foo(x);
}
Смотрим asm:
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
.LC0:
  .string "%s"
foo(int) [clone .part.0]:
  sub rsp, 1032
  mov edi, OFFSET FLAT:.LC0
  xor eax, eax
  mov rsi, rsp
  call scanf
  mov rsi, rsp
  mov edi, OFFSET FLAT:.LC0
  xor eax, eax
  call printf
  add rsp, 1032
  ret
.LC2:
  .string "t: %s"
foo(int):
  sub rsp, 72
  test edi, edi
  jne .L8
  mov rsi, rsp
  mov edi, OFFSET FLAT:.LC0
  xor eax, eax
  call scanf
  mov rsi, rsp
  mov edi, OFFSET FLAT:.LC2
  xor eax, eax
  call printf
  add rsp, 72
  ret
.L8:
  call foo(int) [clone .part.0]
  add rsp, 72
  ret
.LC4:
  .string "%d"
main:
  sub rsp, 24
  mov edi, OFFSET FLAT:.LC4
  xor eax, eax
  lea rsi, [rsp+12]
  call scanf
  mov edi, DWORD PTR [rsp+12]
  call foo(int)
  xor eax, eax
  add rsp, 24
  ret
Как видим, у нас теперь вообще две "функции" foo.
GCC вообще разбил функцию на две и построил подобный код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
void foo_part(int x)
{
   //ветка с массивом в 1024 элемента
}
 
void foo(int x)
{
   //выделение 72 байт
   if (x)
      foo_part(x);
   //ветка с массивом в 64 элемента
}
Так о каких там выделениях при заходе идет речь?
0
Эксперт С++
8972 / 4318 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
12.09.2017, 21:47 23
Цитата Сообщение от ValeryS Посмотреть сообщение
не факт
нет, факт.

Цитата Сообщение от ValeryS Посмотреть сообщение
часто запихиваются в регистр
монопенисуальный фактор.
Цитата Сообщение от ValeryS Посмотреть сообщение
вполне возможен вариант когда область видимости равна "выделению памяти"
не принципиальный момент.

принципиально, что вся память под статические/автоматические объекты
резервируется на этапе компиляции.

на этапе исполнения происходит инициализация объектов.
память же под эти объекты выделяется на этапе запуска процесса.

Добавлено через 1 минуту
Цитата Сообщение от Croessmah Посмотреть сообщение
Так о каких там выделениях при заходе идет речь?
не о женских разумеется.
а о тех, что случаются в момент запуска процесса,
я думаю.
0
Неэпический
18109 / 10696 / 2062
Регистрация: 27.09.2012
Сообщений: 26,933
Записей в блоге: 1
12.09.2017, 21:57 24
Цитата Сообщение от hoggy Посмотреть сообщение
а о тех, что случаются в момент запуска процесса
Это естественно. Только речь о автоматических объектах.
Двигаем указатель, получаем выделение на стеке.
Память же под стек, и, как следствие,
все автоматические объекты выделяется при старте процесса/потока.
Другое дело, когда будут двигаться эти самые "указатели".
C++
1
2
3
{
   int x;//это потенциальный sub/add (конечно же, компилятор всё посчитает. Ага.)
}
Те же самые статические объекты могут быть запиханы прямо в бинарник,
а могут просто просто превратиться число для bss.

Добавлено через 7 минут

Не по теме:

Цитата Сообщение от hoggy Посмотреть сообщение
не о женских разумеется
У кого что болит. Мне этот вариант даже в голову не пришел. :D

1
Notoriously
12.09.2017, 22:12
  #25

Не по теме:

Croessmah,
Да, я же упомянул, что в общем случае - это всё лежит на плечах компилятора.

0
Croessmah
12.09.2017, 22:17
  #26

Не по теме:

Notoriously, я и не спорю. Просто примерчик того, где не всё резервируется при заходе в блок. :)

0
Эксперт С++
8972 / 4318 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
12.09.2017, 22:17 27
Цитата Сообщение от Croessmah Посмотреть сообщение
Другое дело, когда будут двигаться эти самые "указатели".
а это уже совсем другой вопрос.
к выделениям не женским отношения не имеющий.
0
Неэпический
18109 / 10696 / 2062
Регистрация: 27.09.2012
Сообщений: 26,933
Записей в блоге: 1
12.09.2017, 22:20 28
hoggy, наверное, фраза
"резервирование места на стеке под переменные"
подходит лучше, чем
"выделение места на стеке под переменные".
1
Эксперт С++
8972 / 4318 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
12.09.2017, 22:30 29
Цитата Сообщение от Croessmah Посмотреть сообщение
"резервирование места на стеке под переменные"
ни под какие "места для переменных" ничего специально не резервируется.

при запуске процесса ось выделяет ему некоторый кусок под стек.
на этом все выделение резервирования стековой памяти
и заканчивается.

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

то есть, можно сказать,
что компилятор резервирует память под все объекты фрейма функции.
но он резервирует стековую память,
выделением которой он строго говоря не занимается.
1
Неэпический
18109 / 10696 / 2062
Регистрация: 27.09.2012
Сообщений: 26,933
Записей в блоге: 1
12.09.2017, 22:56 30
Цитата Сообщение от hoggy Посмотреть сообщение
ничего специально не резервируется
Цитата Сообщение от hoggy Посмотреть сообщение
то есть, можно сказать,
что компилятор резервирует память
Цитата Сообщение от hoggy Посмотреть сообщение
но он резервирует стековую память
Ы-ы-ы. О чем писали все газеты.
Что, тоже не удалось подобрать более подходящего термина?
Цитата Сообщение от hoggy Посмотреть сообщение
под все объекты фрейма функции.
В коде выше видим, что это не всегда так.
Резервирование может происходить "по месту".
1
Эксперт С++
8972 / 4318 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
12.09.2017, 23:19 31
Цитата Сообщение от Croessmah Посмотреть сообщение
О чем писали все газеты.
газета началась с вопроса: когда создаются объекты.
на этапе загрузки процесса создаются объекты.
объект - кусок памяти(ц)Страуструп.

Цитата Сообщение от Croessmah Посмотреть сообщение
Что, тоже не удалось подобрать более подходящего термина?
не над вырывать из контекста:
Цитата Сообщение от hoggy Посмотреть сообщение
что компилятор резервирует память под все объекты фрейма функции.
но он резервирует стековую память,
выделением которой он строго говоря не занимается.
компилятор на этапе компиляции колбасит стек на фреймы,
так, что бы размера фрейма гарантированно хватило под все его объекты.
а уж хватит ли самого стека...
Кликните здесь для просмотра всего текста
https://youtu.be/uXrKiuG-ybI



Цитата Сообщение от Croessmah Посмотреть сообщение
В коде выше видим, что это не всегда так.
в коде выше мы видим простейшую логику здравого смысла:
есть два объекта: 1 кг и 100 кг.
но жить одновременно они не могут.
следовательно, нет ни одной причины выделять под фрейм 101кг.
100кг хватит на все.
1
Неэпический
18109 / 10696 / 2062
Регистрация: 27.09.2012
Сообщений: 26,933
Записей в блоге: 1
12.09.2017, 23:38 32
Цитата Сообщение от hoggy Посмотреть сообщение
объект - кусок памяти(ц)Страуструп.
An object is a region of storage. (c) ISO/IEC 14882
Цитата Сообщение от hoggy Посмотреть сообщение
в коде выше
И код выше (первом) совершенно не об этом.
Цитата Сообщение от hoggy Посмотреть сообщение
следовательно, нет ни одной причины выделять под фрейм 101кг.
100кг хватит на все.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
 
void foo()
{
    //gcc 4.0.0 резервирует место под оба массива, несмотря на 
    if (rand()) {//взаимоисключающие ветки
        char a2[1512];
        memset(a2, 0, sizeof(a2));
    } else {
        char a2[1512];
        memset(a2, 0, sizeof(a2));
    }
}
 
int main()
{
    foo();
}
0
Эксперт С++
8972 / 4318 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
12.09.2017, 23:44 33
Цитата Сообщение от Croessmah Посмотреть сообщение
An object is a region of storage.
И?

Цитата Сообщение от Croessmah Посмотреть сообщение
Вот сюрприз
Он строго говоря и не обязан умничать.

Так то я бы не удивился,
если бы он догадался подсократить майн до
C++
1
int main() { return 0; }
а там и до всего процесса недалеко.
0
"C with Classes"
2022 / 1404 / 523
Регистрация: 16.08.2014
Сообщений: 5,884
Записей в блоге: 1
13.09.2017, 07:45 34
В самой куче данные могут храниться на стеке?
0
Велосипедист...
353 / 220 / 73
Регистрация: 15.12.2015
Сообщений: 785
13.09.2017, 11:25 35
_stanislav, задам встречный вопрос, который должен стать ответом на Ваш вопрос: в левом кармане может быть правый карман?

Добавлено через 12 минут
Странный однако вопрос. Помнится, Вы писали неплохой код, посмотрев на него и на Ваш код, чувствуется какой-то подвох.
Или код писали не Вы?
0
Неэпический
18109 / 10696 / 2062
Регистрация: 27.09.2012
Сообщений: 26,933
Записей в блоге: 1
13.09.2017, 11:55 36
Цитата Сообщение от Captain Maxee Посмотреть сообщение
в левом кармане может быть правый карман?
Может.
0
Велосипедист...
353 / 220 / 73
Регистрация: 15.12.2015
Сообщений: 785
13.09.2017, 13:13 37

Не по теме:

Croessmah, =-O
Это как? Искусственный стек? Это известный прием? Для чего такое может понадобиться?
( Если долго писать, то дайте направление, где искать )



Добавлено через 2 минуты

Не по теме:

Цитата Сообщение от Captain Maxee Посмотреть сообщение
Вы писали неплохой код, посмотрев на него и на Ваш код
Вы писали неплохой код, посмотрев на него и на Ваш вопрос

0
Неэпический
18109 / 10696 / 2062
Регистрация: 27.09.2012
Сообщений: 26,933
Записей в блоге: 1
13.09.2017, 13:13 38
Цитата Сообщение от Captain Maxee Посмотреть сообщение
Это известный прием?
Достаточно известный.
Цитата Сообщение от Captain Maxee Посмотреть сообщение
Это как?
Дырки в карманах в подкладку,
положил что-то в правый карман,
вытащил потом из левого.
Цитата Сообщение от Captain Maxee Посмотреть сообщение
Для чего такое может понадобиться?
Места больше, хотя использовать неудобно.
Цитата Сообщение от Captain Maxee Посмотреть сообщение
Искусственный стек?
Причем здесь стек? Мы о карманах же.
0
Велосипедист...
353 / 220 / 73
Регистрация: 15.12.2015
Сообщений: 785
13.09.2017, 13:16 39
Цитата Сообщение от Croessmah Посмотреть сообщение
Причем здесь стек? Мы о карманах же.

Я думал, Вы это косвенно про "стек в куче" сказали))
Так уж и быть, сравнение с карманами вышло не очень.
0
"C with Classes"
2022 / 1404 / 523
Регистрация: 16.08.2014
Сообщений: 5,884
Записей в блоге: 1
13.09.2017, 19:58 40
Цитата Сообщение от Captain Maxee Посмотреть сообщение
задам встречный вопрос, который должен стать ответом на Ваш вопрос: в левом кармане может быть правый карман?
я имел ввиду, как реализовано хранение данных в самой куче.
Цитата Сообщение от Captain Maxee Посмотреть сообщение
Или код писали не Вы?
код писал я, причем быстро в лоб, особо не задумываясь, поэтому считаю годным только для примера.
0
13.09.2017, 19:58
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
13.09.2017, 19:58
Помогаю со студенческими работами здесь

Объекты классов в динамической памяти
Я создаю объект класса в динамической памяти ( например map *obj = new map; ) Вопрос: как сделать...

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

Динамическое выделение памяти под объекты
Создать класс с именем TRAIN, содержащий следующие закрытые поля: • название пункта назначения;...

Создать указатели и ссылки на объекты в памяти
Помогите, кто может Создайте в свободной памяти три объекта различных типов (Cat, Worker,...


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

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru