Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.54/13: Рейтинг темы: голосов - 13, средняя оценка - 4.54
 Аватар для taras atavin
4226 / 1796 / 211
Регистрация: 24.11.2009
Сообщений: 27,562

Теория по динамической памяти

13.12.2012, 06:06. Показов 3069. Ответов 41
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Предположим, применяется оператор new в форме для массива:
C++
1
p=new int [n];
. n ведь может быть и большим. Может n==1000000? Где запоминается, сколько выделено памяти и откуда система знает, сколько надо освободить памяти по
C++
1
delete [] p;
? Ведь там то я n не указываю. Может надо освободить сразу много страниц? Освобождаются все страницы, расположенные подряд? Эйси. А если я сначала выделили две страницы, а потом ещё три и все пять оказались подряд? А освобождаю сначала две? За счёт чего система заберёт только первую страницу, а не все пять? Или они не могут быть подряд?
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
13.12.2012, 06:06
Ответы с готовыми решениями:

Освобождение динамической памяти
После первого вызова функции(при повторном) пишет ошибку. В функции sort один из элементов массива становится недоступным для чтения. Если...

Вопрос по динамической памяти
мне надо создать масив содержащий структуры. У меня вот код какой: vec *fild;//vec это название структуры конструктор ...

Удаление new из динамической памяти
Здравствуйте, у меня есть следующее присвоение: sign->numb = new int; Мне нужно от него избавиться в конце программы, но delete...

41
Почетный модератор
7393 / 2639 / 281
Регистрация: 29.07.2006
Сообщений: 13,696
13.12.2012, 06:16
Цитата Сообщение от taras atavin Посмотреть сообщение
Где запоминается, сколько выделено памяти
Например, пишется в область перед выделенным буфером.
0
 Аватар для taras atavin
4226 / 1796 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
13.12.2012, 08:44  [ТС]
То есть дополнительный size_t перед самим блоком? А как оно в винде на самом деле? И может ли к этой инфе достучаться прилада? Чтоб не дублировать её каунтом.

Добавлено через 1 час 4 минуты
Такой:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
int main()
{
 int    *p;
 size_t *s;
 int     i;
 int     start;
 std::cin>>start;
 for (i=1; i<=16; ++i)
 {
  p=new int [i*start];
  s=(size_t*)p;
  std::cout<<i<<", "<<i*start<<", "<<(*s-1)<<std::endl;
  delete [] p;
 }
 return 0;
}
тест показал, что там мусор.
0
654 / 575 / 164
Регистрация: 13.12.2012
Сообщений: 2,124
13.12.2012, 09:55
Цитата Сообщение от taras atavin Посмотреть сообщение
То есть дополнительный size_t перед самим блоком?
нет не там) читай http://www.cplusplus.com/refer... ator%20new[]/

Добавлено через 57 секунд
и это http://www.cplusplus.com/refer... r%20delete[]/
0
 Аватар для taras atavin
4226 / 1796 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
13.12.2012, 10:59  [ТС]
Ещё: откуда new знает, можно ли выделить память в уже имеющейся странице, или уже нет?

Добавлено через 6 минут
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 <iostream>
int main()
{
 int *p[16];
 int  i;
 for (i=15; i>=0; --i)
 {
  p[i]=new int [16];
 }
 for (i=15; i>=0; --i)
 {
  std::cout<<i<<", "<<p[i];
  if (i>0)
  {
   std::cout<<", "<<(p[i]-p[i-1]);
  }
  std::cout<<std::endl;
 }
 for (i=15; i>=0; --i)
 {
  delete [] p;
 }
 return 0;
}
показывает, что иногда несколько раз выделяется память в одной и той же странице.

Добавлено через 17 минут
Цитата Сообщение от aLarman Посмотреть сообщение
нет не там) читай http://www.cplusplus.com/refer... ator%20new[]/
Добавлено через 57 секунд
и это http://www.cplusplus.com/refer... r%20delete[]/
Как применять я знаю и так. А откуда известно, использована ли страница полностью, или нет и какие именно байты из неё можно выдать?
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 <iostream>
int main()
{
 int *p[16];
 int  i;
 for (i=15; i>=0; --i)
 {
  p[i]=new int [2];
 }
 for (i=15; i>=0; --i)
 {
  std::cout<<i<<", "<<p[i];
  if (i>0)
  {
   std::cout<<", "<<(p[i-1]-p[i])<<", "<<((p[i-1]-p[i])/sizeof(int));
  }
  std::cout<<std::endl;
 }
 for (i=15; i>=0; --i)
 {
  delete [] p;
 }
 return 0;
}
показывает, что могут быть выданы много адресов в одной странице. Кстати, почему-то шаг равен размеру одного инта. Откуда делит знает, можно ли у прилады забрать всю страницу?

Добавлено через 30 минут
Сам прогнал, не учёл, что вычитание даёт разницу в сайзофах, а не байтах.
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
28
29
30
#include <iostream>
int main()
{
 int *p[16];
 char *v1;
 char *v2;
 int  i;
 size_t t;
 for (i=15; i>=0; --i)
 {
  p[i]=new int [2];
 }
 for (i=15; i>=0; --i)
 {
  std::cout<<i<<", "<<p[i];
  if (i>0)
  {
   v1=(char *)p[i];
   v2=(char *)p[i-1];
   t=v2-v1;
   std::cout<<", "<<t<<", "<<(t/sizeof(int));
  }
  std::cout<<std::endl;
 }
 for (i=15; i>=0; --i)
 {
  delete [] p;
 }
 return 0;
}
Выделяет почти вплотную.
0
654 / 575 / 164
Регистрация: 13.12.2012
Сообщений: 2,124
13.12.2012, 16:15
Цитата Сообщение от taras atavin Посмотреть сообщение
for (i=15; i>=0; --i)
{
delete [] p;
}
кажется
C++ (Qt)
1
2
3
4
for (i=15; i>=0; --i)
 {
 delete [] p[i];
 }
ну это не суть
в твоем примере тут
C++ (Qt)
1
2
3
4
for (i=15; i>=0; --i)
 {
  p[i]=new int [2];
 }
оператор new выделяет память на 2 элемента типа int и возвращает указатель на начало этого массива, который в итоге записывается в p[i].То, что он должен выделять эти 16 массивов по 2 элемента не означает, что они будут находиться в памяти линейно- где выделилось на то и вернул указатель)
0
Почетный модератор
7393 / 2639 / 281
Регистрация: 29.07.2006
Сообщений: 13,696
13.12.2012, 17:03
Цитата Сообщение от taras atavin Посмотреть сообщение
То есть дополнительный size_t перед самим блоком?
Да.
Цитата Сообщение от taras atavin Посмотреть сообщение
тест показал, что там мусор.
Не смотрел, какой у тебя тест, у меня все нормально:
$ cat ./main.cpp
#include <iostream>

int main()
{
char *a = new char[16];
std::cout<<(long long)*(a-8)<<std::endl;
}
$ g++ main.cpp
$ ./a.out
33
33 - потому что new выделяет память дополнительно к тому, что была запрошена.
Если увеличить кол-во памяти, которое нужно, например, до 64:
$ cat main.cpp
#include <iostream>

int main()
{
char *a = new char[64];
std::cout<<(long long)*(a-8)<<std::endl;
}
$ g++ main.cpp
$ ./a.out
81
Видно, что разница опять на 17.

Добавлено через 15 минут
Цитата Сообщение от Vourhey Посмотреть сообщение
Цитата Сообщение от taras atavin Посмотреть сообщение
То есть дополнительный size_t перед самим блоком?
Да.
Точнее, почти
2
654 / 575 / 164
Регистрация: 13.12.2012
Сообщений: 2,124
13.12.2012, 17:14
Цитата Сообщение от Vourhey Посмотреть сообщение
Не смотрел, какой у тебя тест, у меня все нормально:
$ cat ./main.cpp
#include <iostream>
int main()
{
char *a = new char[16];
std::cout<<(long long)*(a-8)<<std::endl;
}
$ g++ main.cpp
$ ./a.out
33
33 - потому что new выделяет память дополнительно к тому, что была запрошена.
сделал что то подобное
C++
1
2
3
4
5
int *pInt;
    pInt = new int[10];
    for(int i=0;i<10;i++)
        pInt[i]=i;
    cout<<*(pInt-1)<<endl;
при каждом запуске разные числа и я почему то не удивлен) например сейчас получил -33686019

Добавлено через 3 минуты
хотя нет оно не меняется, ибо является мусором и видимо его никто не переписывает, даже если я меняю размер исходного массива, число не меняется) так что не там хранится размер массива)

Добавлено через 3 минуты
Vourhey, а твой пример выдал -98 и так же не меняется с изменением размера массива)
0
Почетный модератор
7393 / 2639 / 281
Регистрация: 29.07.2006
Сообщений: 13,696
13.12.2012, 17:15
Цитата Сообщение от aLarman Посмотреть сообщение
при каждом запуске разные числа и я почему то не удивлен)
Наверное, потому что ты невнимателен.

Добавлено через 38 секунд
Цитата Сообщение от aLarman Посмотреть сообщение
Vourhey, а твой пример выдал -98 и так же не меняется с изменением размера массива)
Ты почитай мое первое сообщение, чтобы глупых вопросов больше не возникало.
0
654 / 575 / 164
Регистрация: 13.12.2012
Сообщений: 2,124
13.12.2012, 17:20
твой пример работает не так как ты пишешь, у меня в частности, проверь сам, что бы не было глупых ответов)
0
Почетный модератор
7393 / 2639 / 281
Регистрация: 29.07.2006
Сообщений: 13,696
13.12.2012, 17:44
Цитата Сообщение от aLarman Посмотреть сообщение
твой пример работает не так как ты пишешь, у меня в частности, проверь сам, что бы не было глупых ответов)
Тяжелый случай...
Цитата Сообщение от Vourhey Посмотреть сообщение
Например, пишется в область перед выделенным буфером.
Слово "например" тебе о чем-то говорит? Тебе оно должно было сказать, что "это зависит от реализации" и один из вариантов - блок перед буфером. Это так же работает не только в g++ Linux, но и в VxWorks.
То, как это работает у тебя - это будет другое "например", поэтому ответь автору по-нормальному, а не пытайся доказать то, что заранее неправда, так как, вариантов несколько.

Добавлено через 17 минут
Цитата Сообщение от aLarman Посмотреть сообщение
int *pInt; pInt = new int[10]; for(int i=0;i<10;i++) pInt[i]=i; cout<<*(pInt-1)<<endl;
Если запускать его в студии, то я бы поменял вот так:
C++
1
2
3
4
5
    int *pInt;
    pInt = new int[10];
    for(int i=0;i<10;i++)
        pInt[i]=i;
    cout<<*(pInt-4)<<endl;
И вывод - 40. Что и есть 10 * размер int. Если поменяю на:
C++
1
pInt = new int[128];
То вывод - 512
0
 Аватар для taras atavin
4226 / 1796 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
13.12.2012, 17:49  [ТС]
Если я триллион раз выделю память и освобожу указатель, то по методе "каждый следующий выделяется впереди" уйдём за границу адресного пространства. По кругу нельзя, так удаляться и снова выделяться мог второй по порядку указатель, а первый существовать всегда. Если выделять только целыми страницами то другая пакость. Может у меня 67108864 динамичских массива по 32 чара? Перерасход адресного пространства в 32768, так как в странице можно разместить 1048576 байт. + уйдём за физическую память, та как страница виртуальной памяти занимает столько же и в физической. А если разделять терминальными страницами, то адресное пространство будет исчерпано в 2 раза быстрее физической памяти. Как ни крути, надо вести учёт байтов, а не страниц. Как это делается в винде?
0
Почетный модератор
7393 / 2639 / 281
Регистрация: 29.07.2006
Сообщений: 13,696
13.12.2012, 17:49
Ну и так...чисто посмотреть на "мусор" в памяти, если брать винду:
0
 Аватар для v.a.l.i.d
425 / 390 / 113
Регистрация: 21.09.2012
Сообщений: 913
13.12.2012, 17:50
Vourhey, Напишите, пожалуйста, как найти количество элементов в дин. массиве float и double. Для int вот это работает
C++
1
cout << "Количество элементов в динамическом массиве: " << *(a - sizeof(a[0])) / sizeof(a[0]) << endl;
а вот для float и double почему то не получается
0
 Аватар для taras atavin
4226 / 1796 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
13.12.2012, 17:55  [ТС]
Цитата Сообщение от Vourhey Посмотреть сообщение
И вывод - 40. Что и есть 10 * размер int. Если поменяю на:
У меня при некоторых размерах наблюдается несколько лишних не выделенных интов между выделенными.

Добавлено через 3 минуты
Цитата Сообщение от v.a.l.i.d Посмотреть сообщение
(a - sizeof(a[0])) / sizeof(a[0]) << endl;
Это работает со статическими. И без разности.
0
Почетный модератор
7393 / 2639 / 281
Регистрация: 29.07.2006
Сообщений: 13,696
13.12.2012, 18:03
Цитата Сообщение от v.a.l.i.d Посмотреть сообщение
Vourhey, Напишите, пожалуйста, как найти количество элементов в дин. массиве float и double. Для int вот это работает
Я вот так сделал: (под виндой, vs 2012)
C++
1
2
3
    float *pInt;
    pInt = new float[32];
    cout<<(int)*((int*)pInt-4)<<endl;
Вывод - 128

Добавлено через 6 минут
taras atavin, насколько я помню (но могу и ошибаться), то каждый последующий не "впереди" выделяется, а ищется свободный непрерывный блок памяти. Он может быть не обязательно "впереди". Но это уже, скорее, относится к менеджеру памяти конкретной ОС, а не к С++.
1
 Аватар для taras atavin
4226 / 1796 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
13.12.2012, 18:04  [ТС]
И без квадратных скобок в числителе. А прямо так даже не компилится: указатели на сайзофы не деляться.
0
 Аватар для v.a.l.i.d
425 / 390 / 113
Регистрация: 21.09.2012
Сообщений: 913
13.12.2012, 18:08
Цитата Сообщение от taras atavin Посмотреть сообщение
Это работает со статическими.
Ну я не знаю. Сейчас делал так и все получается. Вот эта программа у меня всегда правильно результат показывает
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 "stdafx.h"
#include "iostream"
using namespace std;
 
int _tmain(int argc, _TCHAR* argv[])
{
    setlocale(LC_ALL, "Russian");
 
    unsigned int arr_size;
 
    cout << "Введите размер массива: ";
    cin >> arr_size;
 
    int *a = new int[arr_size];
 
    for (int i=0; i<arr_size; i++)
        *(a + i) = (i+1)*10;
 
    cout << "Количество элементов в динамическом массиве int: " << (int)*((int*)a-4) / sizeof(*(a+0)) << endl << endl;
 
    delete [] a;
 
    system("pause")
    return 0;
}
Извиняюсь, не то
0
 Аватар для taras atavin
4226 / 1796 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
13.12.2012, 18:11  [ТС]
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
28
29
30
31
32
33
34
35
36
#include <iostream>
int main()
{
 int *p[16];
 char *v1;
 char *v2;
 int *b;
 int  i;
 size_t t;
 size_t n;
 size_t *s;
 std::cin>>n;
 for (i=15; i>=0; --i)
 {
  p[i]=new int [n];
 }
 for (i=15; i>=0; --i)
 {
  std::cout<<i<<", "<<p[i];
  if (i>0)
  {
   v1=(char *)p[i];
   v2=(char *)p[i-1];
   t=v2-v1;
   s=(size_t *)p[i];
   --s;
   std::cout<<", "<<t<<", "<<(t/sizeof(int))<<", "<<(*s)<< std::endl;
  }
  std::cout<<std::endl;
 }
 for (i=15; i>=0; --i)
 {
  delete [] p;
 }
 return 0;
}
В конце всех строк 1134233773. n вводил 20.

Добавлено через 1 минуту
Цитата Сообщение от v.a.l.i.d Посмотреть сообщение
*(a - sizeof(a[0])) / sizeof(a[0]) << endl;
А, там ещё звёздочка. Щас попробую.

Добавлено через 1 минуту
C++
1
std::cout<<i<<", "<<p[i]<<", "<<(*(p[i] - sizeof(p[i][0]))) / sizeof(p[i][0]);
Выводит 0.
0
Модератор
Эксперт по электронике
8979 / 6745 / 921
Регистрация: 14.02.2011
Сообщений: 23,859
13.12.2012, 18:22
Цитата Сообщение от v.a.l.i.d Посмотреть сообщение
"Количество элементов в динамическом массиве: " << *(a - sizeof(a[0])) / sizeof(a[0])
я вообще то всегда так делал
C++
1
sizeof(a) / sizeof(a[0])
где
sizeof(a) размер всего массива в байтах
sizeof(a[0]) размер первого элемента в байтах
можно написать так (например для double)
C++
1
sizeof(a) / sizeof(double)
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
13.12.2012, 18:22
Помогаю со студенческими работами здесь

Освобождение динамической памяти
Здравствуйте! Была задача реализовать сложение длинных чисел с помощью стеков. Сам стек реализовал просто, но всё же проблемы есть -...

Вопросы по динамической памяти.
У меня вопросы по работе с динамической памятью. Пожалуйста, помогите разобраться с этой темой. - чем отличается free() от delete? и...

Выделение динамической памяти
Ситуация заключается в следующем я выделил память под двумерный массив, но получилось так что мне нужно выделить еще память ...

Освобождение динамической памяти
Добрый день, объясните, пожалуйста, как правильно удалять выделенную динамическую память? Вот пример задачи, где массив произвольного...

Удаление динамической памяти
Всем здрасьте. Имеется вот такая структура. struct ModelType { DWORD FVF; IDirect3DVertexBuffer9* vertexBuffer; ...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Обработчик клика мыши в браузере ПК и касания экрана в браузере на мобильном устройстве
8Observer8 02.02.2026
Содержание блога Для начала пошагово создадим рабочий пример для подготовки к экспериментам в браузере ПК и в браузере мобильного устройства. Потом напишем обработчик клика мыши и обработчик. . .
Философия технологии
iceja 01.02.2026
На мой взгляд у человека в технических проектах остается роль генерального директора. Все остальное нейронки делают уже лучше человека. Они не могут нести предпринимательские риски, не могут. . .
SDL3 для Web (WebAssembly): Вывод текста со шрифтом TTF с помощью SDL3_ttf
8Observer8 01.02.2026
Содержание блога В этой пошаговой инструкции создадим с нуля веб-приложение, которое выводит текст в окне браузера. Запустим на Android на локальном сервере. Загрузим Release на бесплатный. . .
SDL3 для Web (WebAssembly): Сборка C/C++ проекта из консоли
8Observer8 30.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
SDL3 для Web (WebAssembly): Установка Emscripten SDK (emsdk) и CMake для сборки C и C++ приложений в Wasm
8Observer8 30.01.2026
Содержание блога Для того чтобы скачать Emscripten SDK (emsdk) необходимо сначало скачать и уставить Git: Install for Windows. Следуйте стандартной процедуре установки Git через установщик. . . .
SDL3 для Android: Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 29.01.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами. Версия v3 была полностью переписана на Си, в. . .
Инструменты COM: Сохранение данный из VARIANT в файл и загрузка из файла в VARIANT
bedvit 28.01.2026
Сохранение базовых типов COM и массивов (одномерных или двухмерных) любой вложенности (деревья) в файл, с возможностью выбора алгоритмов сжатия и шифрования. Часть библиотеки BedvitCOM Использованы. . .
SDL3 для Android: Загрузка PNG с альфа-каналом с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 28.01.2026
Содержание блога SDL3 имеет собственные средства для загрузки и отображения PNG-файлов с альфа-каналом и базовой работы с ними. В этой инструкции используется функция SDL_LoadPNG(), которая. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru