Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.80/25: Рейтинг темы: голосов - 25, средняя оценка - 4.80
24 / 24 / 8
Регистрация: 02.02.2016
Сообщений: 135

Динамический массив new и его структура выделения памяти?

24.04.2016, 23:58. Показов 6242. Ответов 43
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Доброго времени суток, форумчане!

Долго искал возможность определения размера динамического массива выделенного new (sizeof конечно для указателя не работает).
Все в один голос утверждают - это невозможно!
Я могу конечно хранить где-то размерности своих массивов и потом искать их.
Но чистоты эксперимента ради, есть такая загадка - delete []
Он то определяет размер выделенного массива по указателю. И ПРАВИЛЬНО определяет!
(И почему раньше никто не доказывал этой теоремы от противного?)

Вопрос к знатокам: Как он это делает?
Или пошлите меня по FAQу URLом.

PS Догадываюсь, что хранится эта служебная информация где-то в памяти. Но каков ее формат и точное местоположение?
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
24.04.2016, 23:58
Ответы с готовыми решениями:

Структура и динамический массив
Передо мной стоит задача - создать программу, которая чем-то похожа на макет гаражного кооператива. Короче, пользователь задает число...

Что значат эти строки выделения памяти под массив символов?
что значат эти строки? я так понимаю это значит что выделяется память на 20 символов и если будет больше 20 символов то будет ошибка? ...

Реализовать «массив целых чисел». Обработать ошибки динамического выделения памяти. Переопределить опе
Реализовать класс «массив целых чисел». Обработать ошибки динамического выделения памяти. Переопределить оператор ++ для указателя на...

43
Эксперт С++
 Аватар для Mr.X
3225 / 1752 / 436
Регистрация: 03.05.2010
Сообщений: 3,867
26.04.2016, 08:10
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от Petrolion Посмотреть сообщение
Долго искал возможность определения размера динамического массива выделенного new (sizeof конечно для указателя не работает).
Все в один голос утверждают - это невозможно!
Я могу конечно хранить где-то размерности своих массивов и потом искать их.
Но чистоты эксперимента ради, есть такая загадка - delete []
Он то определяет размер выделенного массива по указателю. И ПРАВИЛЬНО определяет!
(И почему раньше никто не доказывал этой теоремы от противного?)
Вопрос к знатокам: Как он это делает?
А вам не приходило в голову, что это от реализации зависит?
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9007 / 4708 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
26.04.2016, 09:08
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Visual Studio известна тем, что реализует подобный "полиморфизм массивов", как в вашем примере выше. Для того, чтобы поддержать такую функциональность, компилятор Visual Studio для каждого полиморфного типа генерирует два виртуальных деструктора
Так проще же использовать вызов по указателю. Вызываем деструктор по указателю ptr_from_new, затем получаем указатель ptr_from_new+1 и снова вызываем... Тут, как раз, полиморфный вызов сам должен реализовываться без каких-то доп. усилий.
А вот момент увеличения указателя, действительно, интересен тем, что если RTTI не использовать (это нужно один раз и для самого первого объекта, так как мы выяснили, что в перемежку базовый и наследник быть не могут) то из-за того, что размеры у базового и наследника, в общем случае, разные будет неприятность.
Ну что-же... и опять спасибо TheCalligrapher, за ценную информацию. Получается, что нельзя обобщать выделение new и new[] из-за непереносимости.
0
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
26.04.2016, 10:34
IGPIGP, а мне еще доси режит слух, что delete[] не вызовет виртуальные деструктора - хотелось бы цитаты с стандарта и почему никто с КО не пишит об этом в книгах - а тут бац и TheCalligrapher переворачивает жизнь. Странно как-то всё - мб там фраза "реализация лежит на компиляторах", а не UB
0
 Аватар для HighPredator
6045 / 2160 / 753
Регистрация: 10.12.2010
Сообщений: 6,005
Записей в блоге: 3
26.04.2016, 11:11
Я попробую объяснить то, о чем говорит TheCalligrapher из несколько другого угла. Есть раздел в стандарте описывающий выражение delete
In the first alternative (delete object), if the static type of the object to be deleted is different from its dynamic type, the static type shall be a base class of the operand’s dynamic type and the static type shall have a virtual destructor or the behavior is undefined. In the second alternative (delete array) if the dynamic type of the object to be deleted differs from its static type, the behavior is undefined.
И UB к деструкторам здесь имеет в общем-то никакого отношения из-за вот чего. Рассмотрим два случая:
1)
C++
1
Base* ptr = new Base[n];
Здесь мы создали массив из n объектов класса Base. При этом ptr указывает на первый элемент массива.
2)
C++
1
Base* ptr = new Derived[n];
А здесь другое: здесь мы создали массив из n объектов класса Derived, но ptr при этом указывает на подобъект типа Base первого элемента массива, а не на собственно первый элемент массива. Что является нарушением требования для валидного выражения delete[] ptr;
If not, the behavior is undefined. In the second alternative (delete array), the value of the operand of delete may be a null pointer value or a pointer value that resulted from a previous array new-expression.82

82) For non-zero-length arrays, this is the same as a pointer to the first element of the array created by that new-expression.
Отсюда неопределенное поведение.
5
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9007 / 4708 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
26.04.2016, 11:24
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
а мне еще доси режит слух, что delete[] не вызовет виртуальные деструктора
rikimaru2013, как я понял проблема не с деструктором и не с полиморфизмом виртуального деструктора. Сам механизм вызова - вызов по указателю. То есть начиная со второго же объекта нельзя попасть на его начало увеличив указатель базового класса. Что бы всё работало []delete должен иметь багу определять действительный тип и работать с именно его указателем при итерации для последовательного вызова деструкторов. Майкрософт подсуетились и опередили стандарт. На века, похоже.
1
26.04.2016, 11:29

Не по теме:

Цитата Сообщение от IGPIGP Посмотреть сообщение
На века, похоже
:dance:

0
 Аватар для HighPredator
6045 / 2160 / 753
Регистрация: 10.12.2010
Сообщений: 6,005
Записей в блоге: 3
26.04.2016, 11:37
Цитата Сообщение от IGPIGP Посмотреть сообщение
проблема не с деструктором и не с полиморфизмом виртуального деструктора. Сам механизм вызова - вызов по указателю.
Я бы еще сильнее уточнил: сам указатель. В контексте вопроса, ptr по сути своей (мне тут выражение понравилось) "бесполезный" указатель так как указывает на подобъект элемента. То есть с массивом вообще не связанный. Как следствие и индексироваться от такого указателя нереально. Поэтому вполне логично, что и delete[] ptr; не работает. И это в совокупности является хорошей концепцией.
2
Эксперт С++
 Аватар для Mr.X
3225 / 1752 / 436
Регистрация: 03.05.2010
Сообщений: 3,867
26.04.2016, 11:58
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
обычное delete поддерживает полиморфизм, т.е. полиморфное удаление объектов, в то время как delete [] ничего подобного не поддерживает.
Ну дак это вроде бы во всех толковых книжках по С++ написано, что полиморфные объекты невозможно хранить в массивах по значению, а только в массивах указателей на базовый класс. Они ж в общем случае разного размера!
1
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9007 / 4708 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
26.04.2016, 12:29
Выходит, что возможность инициализации указателя базового класса указателем на массив производного класса, это очень удобная и мощная граната.
0
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
26.04.2016, 16:56
Цитата Сообщение от IGPIGP Посмотреть сообщение
То есть начиная со второго же объекта нельзя попасть на его начало увеличив указатель базового класса
а разве увеличение указателя не всегда sizeof( std::size_t ) ??? Еще раз обдумав проблему - не понял проблему)

Деструктор второого объекта это
(адресс на первый + sizeof( std::size_t) * итератор)->__vfptr[индекс вирт метода]
1
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9007 / 4708 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
26.04.2016, 17:01
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
а разве увеличение указателя не всегда sizeof( std::size_t ) ??? Еще раз обдумав проблему - не понял проблему)
Представь, что у тебя массив состоящий из объектов наследника (они в общем случае упитанней родителей)), а смещаться от начала ты будешь на размер родителя за один шаг. С первого же раза до конца наследника сместиться не выйдет даже.
1
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
26.04.2016, 17:11
Цитата Сообщение от IGPIGP Посмотреть сообщение
Представь, что у тебя массив состоящий из объектов наследника
Ой всё, я просто тупой ((( Понял спасибо )
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
13235 / 6867 / 1827
Регистрация: 18.10.2014
Сообщений: 17,413
26.04.2016, 21:16
Цитата Сообщение от IGPIGP Посмотреть сообщение
из-за того, что размеры у базового и наследника, в общем случае, разные будет неприятность.
Вот именно для этого Visual Studio и генерирует специальный "векторный" деструктор для "полиморфных" массивов - этот деструктор знает размер хранимого в массиве объекта.

С этим, кстати, был связан один известный баг в старом-добром VC 6.0. Язык С++ разрешает выделять массивы нулевого размера через new []

C++
1
2
SomeClass *p = new SomeClass[0];
delete [] p;
Однако механизм этих нестандартных "полиморфных массивов" в VC 6.0 накрывался медным тазом в такой ситуации на delete []. delete [] всегда безусловно лезло в самый первый элемент массива за указателем на "векторный" деструктор, забывая при этот о том, что этого первого элемента может и не быть вообще.

Добавлено через 21 минуту
Цитата Сообщение от HighPredator Посмотреть сообщение
Я попробую объяснить то, о чем говорит TheCalligrapher из несколько другого угла. Есть раздел в стандарте описывающий выражение delete
In the first alternative (delete object), if the static type of the object to be deleted is different from its dynamic type, the static type shall be a base class of the operand’s dynamic type and the static type shall have a virtual destructor or the behavior is undefined. In the second alternative (delete array) if the dynamic type of the object to be deleted differs from its static type, the behavior is undefined.
Именно выделенную фразу я и привел/перевел здесь в виде "В delete [], если статический тип удаляемого объекта не совпадает с динамическим типом, то поведение не определено."
1
393 / 165 / 32
Регистрация: 10.12.2015
Сообщений: 717
26.04.2016, 21:29
До конца не дочитал. М.б. и пропустил что-то. Кто-то задавался следующим вопросом? c++ язык высокого уровня, компилирует код в нативный под конкретную_платформу/ос, конкретная ОС имеет в своем составе MM, который и занимается управлением памятью. Может кто-то попытался пропустить исполняемый модуль через strace, например (это я намекаю)? Программе вовсе не обязательно "знать" размер массива, она его и "не знает", а всего лишь говорит ядру "дай мне столько памяти" и ядро возвращает адрес нулевой страницы. Потом процесс говорит ядру "эта память мне больше не нужна" и ядро перераспределяет страницы по своим заумным алгоритмам. Как публике такое объяснение?
0
24 / 24 / 8
Регистрация: 02.02.2016
Сообщений: 135
26.04.2016, 22:40  [ТС]
Цитата Сообщение от IGPIGP Посмотреть сообщение
Ссылку от tapochka смотрели?
Вот вся тема:
Можно ли обойти динамический массив не зная его размер?
Посмотрел эту тему еще раз, посмотрел ссылки из нее.
Нового для себя к сожалению ничего не нашел. Точнее нашел, но все не по теме. А это уже демагогия (достижение любых целей кроме реальной).
Для себя вынес, что: как реально работает связка компилятор-менеджер памяти не знает никто. Ибо нет универсального механизма и каждый реализует как хочет. Главное чтобы удовлетворяло стандарту C.
А значит я не совсем корректно задал вопрос. Надо было внести корректировку, что интересен механизм выделения памяти под встроенные типы переменных для MSVS.
К сожалению и в этом топике нет реального ответа.
Как говорят: "Тема Си... не раскрыта".

ЗЫ. Ну может когда-нибудь, человек знающий этот механизм, ответит.
0
7804 / 6568 / 2988
Регистрация: 14.04.2014
Сообщений: 28,705
26.04.2016, 23:01
Petrolion, а я три раза прочитал твоё сообщение и не понял, что ты хочешь. Сначала говоришь, что вынес для себя, что каждый реализует как хочет, затем что-то про встроенные типы.
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
13235 / 6867 / 1827
Регистрация: 18.10.2014
Сообщений: 17,413
26.04.2016, 23:05
Цитата Сообщение от Petrolion Посмотреть сообщение
Для себя вынес, что: как реально работает связка компилятор-менеджер памяти не знает никто.
"Как реально работает связка компилятор-менеджер памяти" - определяется реализацией. Никаких стандартов тут нет. Как вы сами заметили, "Главное чтобы удовлетворяло стандарту C." С той только поправной, что мы тут о С++ говорим, а не о С.

Однако в ветке по ссылке я детально описал, как это делается в большинстве реальных реализаций. (Я скромничаю, когда, говорю "в большинстве". На само деле так делается везде). Никакой "демагогии" там нет. Именно так все это и работает.

Цитата Сообщение от Petrolion Посмотреть сообщение
А значит я не совсем корректно задал вопрос. Надо было внести корректировку, что интересен механизм выделения памяти под встроенные типы переменных для MSVS.
Мой ответ в ветке по ссылке детально закрывает этот вопрос.

Цитата Сообщение от Petrolion Посмотреть сообщение
К сожалению и в этом топике нет реального ответа.
Вам показалось.

Цитата Сообщение от Petrolion Посмотреть сообщение
Как говорят: "Тема Си... не раскрыта".
Вы определитесь, о чем вы спрашиваете: о С или о С++. А то начинают мучать смутные сомнения.
1
393 / 165 / 32
Регистрация: 10.12.2015
Сообщений: 717
26.04.2016, 23:09
Цитата Сообщение от Petrolion Посмотреть сообщение
как реально работает связка компилятор-менеджер памяти не знает никто
Я знаю. Нет такой связки. Компилятор знает целевую api. Этого достаточно с головой чтобы построить код.

TheCalligrapher, я читал твой пост с развернутым ответом. Всё четко. У меня только закралось парочка философских вопросов, а зачем это вообще надо? Сишные компиляторы тоже так поступают?
0
24 / 24 / 8
Регистрация: 02.02.2016
Сообщений: 135
26.04.2016, 23:34  [ТС]
to TheCalligrapher
Конечно мы говорим о C++
А в конце была несколько измененная известная летучая фраза :-)

Но что было из начальных вопросов...
1. Структура выделения памяти в динамических массивах.
2. Формат и точное местоположение этой служебной информации.
3. Как delete [] определяет размер возвращаемой памяти.
Все три вопроса, как видно, тесно связаны. И еще скорректировано рассматриваются для MSVS и их встроенных типов данных (long long, int, char,....)
Возможно я совсем не просветленный, но конкретностей в топиках для данных вопросов, простите, не увидел.

Не хочу никого обидеть, но если бы так описывались форматы, к примеру FAT, возникало бы вопросов больше чем было до чтения формата.
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
13235 / 6867 / 1827
Регистрация: 18.10.2014
Сообщений: 17,413
26.04.2016, 23:43
Цитата Сообщение от cyber-satyr Посмотреть сообщение
TheCalligrapher, я читал твой пост с развернутым ответом. Всё четко. У меня только закралось парочка философских вопросов, а зачем это вообще надо? Сишные компиляторы тоже так поступают?
Я не совсем понимаю вопроса.

В языке С нигде не необходимости знать размер выделенного блока динамической памяти на уровне "ядра языка" (core language). Т.е. компилятору С эта тема не интересна вообще. Вопросы размера блока динамической памяти там решаются на уровне библиотеки - размер блока просто записывается в начало блока функциями библиотеки и читается оттуда функциями библиотеки.

А вот в языке С++ эта тема уже "проникает" на уровень ядра языка - компилятору иногда надо знать, сколько деструкторов вызывать. Поэтому структура блока, выделенного new [] - это вопрос уровня ядра языка, уровня компилятора.

"Сколько деструкторов вызывать" - это и есть, "зачем это вообще" надо. Там же вроде детально объяснялось.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
26.04.2016, 23:43

Структура: Сделать динамический массив структур клиентов банка...
Нужно сделать динамический массив структур клиентов банка, хочу сделать так что бы при каждом добавлении клиента под него выделялась...

Составить программу для выделения D - экстремального подмножества в заданном графе согласно указанному алгоритму его выделения
Задание. Составить программу для выделения D - экстремального подмножества в заданном графе согласно указанному алгоритму его ...

Очищение памяти (одномерный динамический массив)
Здравствуйте, у меня возникла проблема с высвобождением памяти при одномерном динамическом массиве: #include <iostream> #include...

Перевыделение памяти в функции - динамический массив
Доброе время суток, Подскажите как сделать такую задачу Только перешел на динамические массивы За ранее благодарен Описать массив...

Динамический массив: программа выдает ошибку памяти
Вот программа, выдает ошибку памяти как её исправить? не получается #include "stdafx.h" #include <iostream> #include...


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

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
Генератор паролей (вариант №4)
Maks 01.11.2026
После публикации 3-го варианта генератора паролей, разослал его своим коллегам (с целью оценки), в итоге были получены следующие рекомендации: 1. Вернуть возможность использования знаков | 1 l I;. . .
Генератор паролей (вариант №3)
Maks 30.10.2026
Финальная версия генератора паролей 1С. Доработка решения в этот раз коснулась только визуальной части, а именно, добавлен реквизит ДопПараметры (тип Булево), который скрывает/ отображает реквизиты:. . .
Магическое мышление и магия, современная наука не отличима от магии (говорит ИИ Джемени)
zorxor 30.10.2026
Джемени, расскажи, пожалуйста, что такое магическое мышление, что такое магия, почему современная наука чем-то напоминает магию? Фраза «Любая достаточно развитая технология неотличима от магии». . .
За какое время ИИ может подобрать пароль по хешу (рассказывает Джемени ИИ)
zorxor 30.10.2026
Расскажи, Джемени, если известен хэш МД5, например, за сколько ИИ сможет подобрать соответствующий пароль? Искусственный интеллект (ИИ) может подобрать простой или средний по сложности пароль по. . .
Кто убил Suno? Почему наше солнышко погасло? (диалог с ИИ Джемени)
zorxor 30.10.2026
Как убивали Suno. Хронология. «Убийство» музыкальной нейросети Suno — это затяжной процесс, в котором технологический хайп стартапа разбился о жесткую реальность судебных исков от гигантов. . .
Генератор паролей (вариант №2)
Maks 30.10.2026
Обновленная версия ранее созданной обработки. Добавлены следующие реквизиты типа Булево: - Буквы; - Цифры; - Символы. Изменена логика команды "Сгенерировать" и процедуры "ПриОткрытии":. . .
Генератор паролей (вариант №1)
Maks 29.10.2026
Реализация из решения ниже выполнена исключительно по моей инициативе, дабы облегчить себе работу в создании паролей для администрируемых мною сервисов и пользователей. Самым главным критерием для. . .
Установка ChatGPT (Codex) на Windows без использования Microsoft Store
Fabien159 28.10.2026
Здравствуйте всем читающим! Опишу процесс установки ChatGPT (Codex) на Windows, если по каким-то причинам у вас не получается устанавить его через Microsoft Store. И так: 1. Скачиваем с. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru