2010-04-13 4 views
6

Это может быть очень простой вопрос, но, пожалуйста, помогите мне.delete & new in C++

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

char * ptr=new char [10]; 

delete [] ptr; 

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

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

Большое спасибо

+2

Может быть полезным: http://stackoverflow.com/questions/2327848/how-does-the-delete-in-c-know-how-many-memory-locations-to-delete – codaddict

ответ

13

ли он выделить точные 10 байт

Это зависит от реализации. Гарантия «не менее 10 символов».

Где хранится информация о размере?

Это зависит от реализации.

Есть ли заголовок для каждого нового, который содержит информацию о количестве байт, выделенных новым?

Это зависит от реализации.

Под «это зависит от реализации» Я имею в виду, что он не определен в стандарте.

0
char * ptr=new char [10]; 

Вы создаете массив 10 персонажа в куче и хранить адрес 0-го элемента в pointer.this аналогично делать в таНос в C

delete [] ptr; 

Вы удаляете (освобождая память) память кучи, которая была назначена более ранним выражением. Это похоже на выполнение free в c.

3

Это полностью зависит от реализации. В общем случае вам нужно сохранить количество элементов в другом месте. Реализация должна выделять достаточно места для, по крайней мере, количества указанных элементов, но может выделять больше.

3

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

Это зависит от платформы, но да, на многих платформах есть.

5

Это все, что связано с компилятором и библиотекой времени выполнения. Это точно определено, какие эффекты у new и delete есть в вашей программе, но как именно они выполняются, не указывается.

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

2

Точно, согласно стандарту, new char[10] будет выделять не менее 10 байтов в куче.

Внутренние элементы new и delete зависят от реализации. Таким образом, он будет варьироваться от компилятора к компилятору и от платформы к платформе. Кроме того, вы можете найти множество алгоритмов распределения (например: TCMalloc).

Я дам вам обзор того, как это может работать внутренне, но не воспринимать его как абсолютную истину. Это написано исключительно для этого объяснения.

Короче говоря, оператор new внутренне вызывает malloc. malloc использует действительно длинный связанный список доступных блоков памяти, aka free chain. Когда вызывается malloc, он ищет этот список для первого блока, который достаточно велик, чтобы удерживать запрошенный размер. После этого он разбивает блок на две части: один с размером, который вы запросили, а другой с остальным, который затем добавляется обратно в свободную цепочку. Наконец, он возвращает блок с размером запроса.

Обратный происходит в вызове free, который вызывается delete/delete []. Короче говоря, он помещает предоставленный блок обратно в free chain.

В ходе описанных выше процессов могут возникнуть причудливые трюки, например сортировка free chain, округление запрошенного размера до следующей мощности по 2 для уменьшения фрагментации памяти и т. Д.

+0

'new' doesn Не нужно полагаться на 'malloc'.Это тоже зависит от реализации :) –

+0

@ Правильно, если я не сделал 2-е предложение ясным, дайте мне знать, поэтому я могу уточнить. Или добавьте дополнительный комментарий перед обзором. Это было в основном дать представление о том, как это работает. – jweyrich

0

Это зависит от реализации, но в основном метаданные для блока памяти обычно хранятся в области до возврата адреса памяти. Изменения, которые вы наблюдали перед 10 байтами, были, вероятно, метаданными, обновляемыми для этого блока (вероятно, размер блока, записываемого в метаданные), и после того, как 10 байтов были обновлены метаданные для следующего блока (все еще нераспределенные, вероятные указатель на следующий фрагмент в свободном списке).

Неплохо быть с кучей, поскольку оно не переносится. Однако, если вы хотите сделать такую ​​кучу магии, я предлагаю вам реализовать свои собственные пулы памяти (просто получайте большой кусок памяти из кучи и управляйте ею самостоятельно). Возможное место для начала - посмотреть на libmm.

0

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

Причина этого в том, что если массив объектов присваивается новым [], когда они удаляются с помощью delete [], необходимо вызвать деструктор каждого объекта в массиве. delete [] должен знать, сколько объектов нужно уничтожить. Именно поэтому необходимо сопоставить новое с delete и new [] с delete [].