new для выделения памяти под массив ( new char[ 10 ] )
От: ZZTop  
Дата: 24.09.03 16:15
Оценка:
Вопрос :
1) Я выделяю память например так:
char* pChar = new char[10];
при вызове "delete pChar" удалится вся память ?
2) Каковы различия в вызовах "delete [] pChar" и "delete pChar" ?
Re: new для выделения памяти под массив ( new char[ 10 ] )
От: Вадим Никулин Россия Здесь
Дата: 24.09.03 16:31
Оценка:
Здравствуйте, ZZTop, Вы писали:

ZZT>Вопрос :

ZZT>1) Я выделяю память например так:
ZZT>char* pChar = new char[10];
ZZT>при вызове "delete pChar" удалится вся память ?
ZZT>2) Каковы различия в вызовах "delete [] pChar" и "delete pChar" ?

1. Правильно в этом случае делать delete[].
2. Различия проявляются в случае, если объекты имеют нетривиальные деструкторы.
Re: new для выделения памяти под массив ( new char[ 10 ] )
От: Аноним  
Дата: 24.09.03 16:40
Оценка:
Здравствуйте, ZZTop, Вы писали:

ZZT>1) Я выделяю память например так:

ZZT>char* pChar = new char[10];
ZZT>при вызове "delete pChar" удалится вся память ?

В некоторых (возможно даже, в большинстве) средах разработки тебе может повезти и этот вызов будет отработан так же, как и правильный:
delete[] pChar;


Но вообще это вилами на воде писано.

ZZT>2) Каковы различия в вызовах "delete [] pChar" и "delete pChar" ?


Правило тривиально: память, выделенная посредством new, должна высвобождаться посредством delete; память, выделенная посредством new[], должна высвобождаться посредством delete[].

Различие между ними является необходимым при освобождении массивов объектов, обладающих деструкторами, т. к. необходимо обеспечить не только освобождение памяти, но и корректный вызов деструктора для каждого объекта. Для этого нужно иметь отличный от случая одиночного объекта формат разметки выделенного блока.
Re: new для выделения памяти под массив ( new char[ 10 ] )
От: Андрей Тарасевич Беларусь  
Дата: 24.09.03 18:19
Оценка:
Здравствуйте, ZZTop, Вы писали:

ZZT>Вопрос :

ZZT>1) Я выделяю память например так:
ZZT>char* pChar = new char[10];
ZZT>при вызове "delete pChar" удалится вся память ?

Вызов 'delete pChar' в данном случае приводит к неопределенному поведению. Для удаления объектов типа "массив" применяется 'delete[]' и только 'delete[]'

ZZT>2) Каковы различия в вызовах "delete [] pChar" и "delete pChar" ?


'delete[]' применяется для удаления объектов типа "массив". 'delete' применяется для удаления одиночных объектов.
Best regards,
Андрей Тарасевич
Re[2]: new для выделения памяти под массив ( new char[ 10 ]
От: Андрей Тарасевич Беларусь  
Дата: 24.09.03 18:22
Оценка:
Здравствуйте, Вадим Никулин, Вы писали:

ZZT>>Вопрос :

ZZT>>1) Я выделяю память например так:
ZZT>>char* pChar = new char[10];
ZZT>>при вызове "delete pChar" удалится вся память ?
ZZT>>2) Каковы различия в вызовах "delete [] pChar" и "delete pChar" ?

ВН>1. Правильно в этом случае делать delete[].


ВН>2. Различия проявляются в случае, если объекты имеют нетривиальные деструкторы.


Совсем не обязательно только в этом случае. Механизмы 'new/delete' и 'new[]/delete[]' могут быть принципиально различными. Смешивание этих способов выделения/освобождения памяти потенциально ведет к неопределенному поведению независимо от характеристик деструктров объектов.
Best regards,
Андрей Тарасевич
Re[3]: new для выделения памяти под массив ( new char[ 10 ]
От: Аноним  
Дата: 25.09.03 06:35
Оценка:
Здравствуйте, Андрей Тарасевич, Вы писали:

АТ>Совсем не обязательно только в этом случае. Механизмы 'new/delete' и 'new[]/delete[]' могут быть принципиально различными. Смешивание этих способов выделения/освобождения памяти потенциально ведет к неопределенному поведению независимо от характеристик деструктров объектов.


А delete[] знает о типе объектов?
например такое нормально?
char* pc = new[16];
long* pl = reinterpret_cast< long* >( pc );
delete[] pl;


а такое?
ClassA* pA = new ClassA[16];
ClassB* pB = reinterpret_cast< ClassB* >( pA );
delete[] pB;


А если выделить массив char, потом сделать placement new и освобождать память как массив объектов?
Будут корректно вызваны деструкторы объектов в массиве?
Re[4]: new для выделения памяти под массив ( new char[ 10 ]
От: Anton V. Kolotaev  
Дата: 25.09.03 07:50
Оценка:
Здравствуйте, Аноним, Вы писали:

А>А delete[] знает о типе объектов?


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

А>например такое нормально?

А>
А>char* pc = new[16];
А>long* pl = reinterpret_cast< long* >( pc );
А>delete[] pl;
А>


Вполне.

А> а такое?

А>
А>ClassA* pA = new ClassA[16];
А>ClassB* pB = reinterpret_cast< ClassB* >( pA );
А>delete[] pB;
А>


Память освободится, однако вызовутся деструкторы ClassB.
Re[5]: new для выделения памяти под массив ( new char[ 10 ]
От: Павел Кузнецов  
Дата: 25.09.03 08:15
Оценка:
Здравствуйте, Anton V. Kolotaev, Вы писали:

А>> например такое нормально?

А>>
А>> char* pc = new[16];
А>> long* pl = reinterpret_cast< long* >( pc );
А>> delete[] pl;
А>>


AVK> Вполне.


Не вполне: undefined behavior.

А>> а такое?

А>>
А>> ClassA* pA = new ClassA[16];
А>> ClassB* pB = reinterpret_cast< ClassB* >( pA );
А>> delete[] pB;
А>>


AVK> Память освободится, однако вызовутся деструкторы ClassB.


Одно из возможных проявлений неопределенного поведения, но далеко не единственное.
Posted via RSDN NNTP Server 1.7 "Bedlam"
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[6]: new для выделения памяти под массив ( new char[ 10 ]
От: Аноним  
Дата: 25.09.03 09:07
Оценка:
Здравствуйте, Павел Кузнецов, Вы писали:


ПК>Не вполне: undefined behavior.


Т.е. надо внимательно следить за тем, какой тип используется при выделении, а какой при удалении?
Re[7]: new для выделения памяти под массив ( new char[ 10 ]
От: Павел Кузнецов  
Дата: 25.09.03 09:22
Оценка:
Здравствуйте, Вы писали:

> Т.е. надо внимательно следить за тем, какой тип используется при

> выделении, а какой при удалении?

Да.
Posted via RSDN NNTP Server 1.7 "Bedlam"
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[4]: new для выделения памяти под массив ( new char[ 10 ]
От: adontz Грузия http://adontz.wordpress.com/
Дата: 25.09.03 11:22
Оценка:
Здравствуйте, Аноним, Вы писали:

А>например такое нормально?

А>
А>char* pc = new[16];
А>long* pl = reinterpret_cast< long* >( pc );
А>delete[] pl;
А>


Учитывая, что оба типа не обладают деструкторами, то плохого не будет. Но вообще говоря (если говорить о двух произвольных разных типах) такое использование delete[] приведёт к ошибке.

А> а такое?

А>
А>ClassA* pA = new ClassA[16];
А>ClassB* pB = reinterpret_cast< ClassB* >( pA );
А>delete[] pB;
А>


Ошибка.

А>А если выделить массив char, потом сделать placement new и освобождать память как массив объектов?

А>Будут корректно вызваны деструкторы объектов в массиве?

Пример:


class test
 {
  protected:
   int x;
  public:
   test() {x = 1;}
   ~test() {x = 0;}
 }

int main(char *, int)
 {
  test * lpTest = new test[4];
 }


У оператора new будет запрошено 4*sizeof(test) + sizeof(int) = 4*4+4 = 20 байт
Почему? Потому что в начале массива используеться 4 байта для хранения его размера в элементах. А чтоб мы этого не заметили они фактически ДО возвращаемого нам указателя
delete[] и new[] в том виде в каком он работает (для VC6/7) можно описать так

template<class TYPE>
TYPE * New(unsigned int size)
{
 int arraySize = size + sizeof(int);
 TYPE * lpMemory = (TYPE *)(((unsigned int)malloc(arraySize)) + sizeof(int));
 if (lpMemory == (- sizeof(int))) return NULL
 for (unsigned int i = 0; i < size/sizeof(TYPE); i++)
  {
   (lpMemory + i)->TYPE();
  }
 return lpMemory;
}

template<class TYPE>
void Delete(TYPE * lpMemory)
{
 int arraySize = *((int *)(((unsigned int)lpMemory) - sizeof(int)));
 for (unsigned int i = 0; i < arraySize; i++)
  {
   (lpMemory + i)->~TYPE();
  }
 free(lpMemory);
}
A journey of a thousand miles must begin with a single step © Lau Tsu
Re[5]: new для выделения памяти под массив ( new char[ 10 ]
От: Павел Кузнецов  
Дата: 25.09.03 12:14
Оценка:
Здравствуйте, adontz, Вы писали:

А>> например такое нормально?

А>>
А>> char* pc = new[16];
А>> long* pl = reinterpret_cast< long* >( pc );
А>> delete[] pl;
А>>


a> Учитывая, что оба типа не обладают деструкторами, то плохого не будет.


Undefined behavior. Проявления зависят от реализации. Например, для char[] и для long[]
вполне могут резервироваться заголовки различного размера, что в приведенном примере приведет
к феерверку в связи с освобождением памяти не по тому адресу, по которому она выделялась.
Posted via RSDN NNTP Server 1.7 "Bedlam"
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[6]: new для выделения памяти под массив ( new char[ 10 ]
От: adontz Грузия http://adontz.wordpress.com/
Дата: 25.09.03 12:45
Оценка:
Здравствуйте, Павел Кузнецов, Вы писали:

ПК>Undefined behavior. Проявления зависят от реализации. Например, для char[] и для long[]

ПК>вполне могут резервироваться заголовки различного размера,

А зачем вообще заголовки типам без деструктора? С чего бы им создаваться? Нет я не спорю, что может по стандарту оно и Undefined но по жизни оно канкретна Defined
A journey of a thousand miles must begin with a single step © Lau Tsu
Re[7]: new для выделения памяти под массив ( new char[ 10 ]
От: Павел Кузнецов  
Дата: 25.09.03 13:12
Оценка:
Здравствуйте, adontz, Вы писали:

ПК>> Undefined behavior. Проявления зависят от реализации. Например, для

ПК>> char[] и для long[] вполне могут резервироваться заголовки
ПК>> различного размера,

a> А зачем вообще заголовки типам без деструктора?


Например, для какой-нибудь диагностики границ массивов. Или потому что разработчики
компилятора не тратили время на оптимизацию заголовков для POD-типов etc.
Posted via RSDN NNTP Server 1.7 "Bedlam"
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.