Re[6]: delete [ ] или delete?
От: Кодт Россия  
Дата: 27.09.05 16:24
Оценка: 1 (1)
Здравствуйте, WinterMute, Вы писали:

WM>Я, конечно, неправильно выразился, не комплятор знает, а менеджер памяти знает. С той оговоркой, что я не очень хорошо представляю как менеджер памяти работает, я всё-таки предположу как оно всё происходит: если мы пишем delete [] arrPtr, то, компилятор встявляет код, который обращается к менеджеру памяти, чтобы узнать, сколько обектов выделено по этому адресу, для всех них вызываются деструкторы, потом менеджер памяти освобождает этот кусок. Если написать delete arrPtr, то, скорее всего вызовется деструктор только первого объекта, память освободится вся. Т.е., если заставить компилятор всегда смотреть, сколько объектов выделено по этому адресу(эта информация всегда доступна), то можно обойтись одним оператором, разумеется, работать это будет чуть медленнее.


WM>Или я жестоко заблужаюсь?


Заблуждаешься.
1) Менеджеры памяти для operator new и operator new[] могут быть вообще разные.
2) Даже если одинаковые, то такой подход сделает невозможным работу placement new — потому что выражение new всегда будет пытаться записать эту информацию в предоставленный буфер.
Перекуём баги на фичи!
Re[4]: delete [ ] или delete?
От: Bell Россия  
Дата: 27.09.05 13:52
Оценка: +1
Здравствуйте, bayda, Вы писали:


B>что такое UB?

Неопределенное поведение (Undefined Behavior).

B>>>...кажется об этом даже Страуструп говорил, что встроенных типов ты можышь не писать [].

B>>Ссылку на первоисточник можно привести?
B>если очень интересно, то я сегодня вечером (после работы) либо завтра сутра
B>поищу повспоминаю откуда я это взял

Было бы любопытно.
Ну а предварительно можно заглянуть в стандарт, пункт 5.3.5/2
Любите книгу — источник знаний (с) М.Горький
Re[2]: delete [ ] или delete?
От: Bell Россия  
Дата: 27.09.05 15:25
Оценка: +1
Здравствуйте, WinterMute, Вы писали:

WM>Кстати, а не синтаксический ли это оверхед? Компилятор ведь сам может определить что стоит справа указатель на элемент, или указатель на массив.


Да ну?


extern void my_free(some_struct* ptr);
int main()
{
   my_free(new some_struct());
   my_free(new some_struct [10]);

   return 0;
}

//там вдали за рекой
void my_free(some_struct* ptr)
{
   //как тут определить, что есть ptr ?
}
Любите книгу — источник знаний (с) М.Горький
delete [ ] или delete?
От: mavius Россия http://mavius.narod.ru
Дата: 27.09.05 12:57
Оценка:
Постоянно натыкаюсь на эту непонятку, и, опять же, не понимаю, почему другим это не непонятно
// Иногда приходиться создавать динамические массивы, например:

DWORD* a = new DWORD[20];


// потом производить хитрые операции,
// и, когда этот массив следует удалить,
// я всегда поступаю так:

delete a;


// А, вот, дядя Страустрап и все остальные мегапрограммеры применяют такую хитрую форму:

delete[] a;


// Спрашивается, что нам это даёт и зачем существует в природе?
Re: delete [ ] или delete?
От: Alxndr Германия http://www.google.com/profiles/alexander.poluektov#buzz
Дата: 27.09.05 13:03
Оценка:
Здравствуйте, mavius, Вы писали:

M>
DWORD* a = new DWORD[20];

M>
delete a;


Ты поступаешь неправильно.

M>
delete[] a;


M>// Спрашивается, что нам это даёт и зачем существует в природе?


Это дает нам вызов деструкторов элементов массива и избавления от неопределенного поведения (UB).
Смотри любой учебник по С++.
Re: delete [ ] или delete?
От: Константин http://flint-inc.ru/
Дата: 27.09.05 13:04
Оценка:
Здравствуйте, mavius, Вы писали:

M>// Спрашивается, что нам это даёт и зачем существует в природе?


Тут уже обсуждалось не раз, поройся поиском. А если вкратце — то для удаления массивов надо использовать именно delete[]. Во-первых, никто не гарантирует, что в данном конкретном компиляторе delete будет корректно удалять массивы, он же предназначен для удаления единичных объектов (хотя все нормальные компиляторы делают это корректно). А во-вторых (это важно для работы с классами, а не с простыми типами), delete[] вызовет деструкторы для всех элементов массива, а delete — только для одного.
Почему же, ё-моё, ты нигде не пишешь «ё»?
Re: delete [ ] или delete?
От: Bell Россия  
Дата: 27.09.05 13:06
Оценка:
Здравствуйте, mavius, Вы писали:

В С++ new и new[] — разные вещи. Тоже относится и к delete/delete []. Поэтому нужно следовать правилу:
выделил new — освободил delete; выделил new [] — освободил delete []. Путаница ведет к неопределенному поведению.

на практике часто бывает, что для встроенных типов связка new[]/delete работает нормально. Но для user-defined типов все далеко не так безоблачно.
Чтобы не быть голословным, вот небольшой примерчик.

#include <iostream>

struct test
{
   test() { std::cout << "ctor\n";}

   ~test() { std::cout << "dtor\n";}
};


int main()
{
   test* p = new test[10];
   delete p;
   return 0;
}
Любите книгу — источник знаний (с) М.Горький
Re: delete [ ] или delete?
От: GregZ СССР  
Дата: 27.09.05 13:11
Оценка:
Здравствуйте, mavius, Вы писали:

M>Постоянно натыкаюсь на эту непонятку, и, опять же, не понимаю, почему другим это не непонятно

M>// Иногда приходиться создавать динамические массивы, например:

M>
DWORD* a = new DWORD[20];

M>
delete a;


M>// А, вот, дядя Страустрап и все остальные мегапрограммеры применяют такую хитрую форму:


M>
delete[] a;


M>// Спрашивается, что нам это даёт и зачем существует в природе?


При вызове delete вызывается один или несколько деструкторов, а затем посредством функции operator delete освобождается память.
Что случиться если не использовать delete[] для удаления массивов? Неизвестно. Более того, это не определено даже для встроенных типом, подобных int, несмотря на то, что у таких типов нет деструкторов.
Re: delete [ ] или delete?
От: bayda Украина  
Дата: 27.09.05 13:28
Оценка:
Здравствуйте, mavius, Вы писали:

M>Постоянно натыкаюсь на эту непонятку, и, опять же, не понимаю, почему другим это не непонятно



Данетже, delete без [] ты можышь вызывать и для масивов, только деструктор не вызвится,
кажется об этом даже Страуструп говорил, что встроенных типов ты можышь не писать [].
А вот для объектов надо писать, чтобы для всех вызвался деструктор помимо освобождения памяти.

Ну и плюсь читабельность, для нее всё же лучше писать [] если осовобождаешь масив.
Re[2]: delete [ ] или delete?
От: Bell Россия  
Дата: 27.09.05 13:34
Оценка:
Здравствуйте, bayda, Вы писали:

B>Данетже, delete без [] ты можышь вызывать и для масивов, только деструктор не вызвится,

Неверно. Это UB.

B>...кажется об этом даже Страуструп говорил, что встроенных типов ты можышь не писать [].

Ссылку на первоисточник можно привести?
Любите книгу — источник знаний (с) М.Горький
Re[3]: delete [ ] или delete?
От: bayda Украина  
Дата: 27.09.05 13:41
Оценка:
Здравствуйте, Bell, Вы писали:

B>Здравствуйте, bayda, Вы писали:


B>>Данетже, delete без [] ты можышь вызывать и для масивов, только деструктор не вызвится,

B>Неверно. Это UB.
что такое UB?

B>>...кажется об этом даже Страуструп говорил, что встроенных типов ты можышь не писать [].

B>Ссылку на первоисточник можно привести?
если очень интересно, то я сегодня вечером (после работы) либо завтра сутра
поищу повспоминаю откуда я это взял
Re[4]: delete [ ] или delete?
От: Анатолий Широков СССР  
Дата: 27.09.05 13:56
Оценка:
Здравствуйте, bayda, Вы писали:

B>Здравствуйте, Bell, Вы писали:


B>>Здравствуйте, bayda, Вы писали:


B>>>Данетже, delete без [] ты можышь вызывать и для масивов, только деструктор не вызвится,

B>>Неверно. Это UB.
B>что такое UB?

UB — неопределенное поведение — то есть, компилятор вправе сделать все что угодно и ему за это ничего не будет

B>>>...кажется об этом даже Страуструп говорил, что встроенных типов ты можышь не писать [].

B>>Ссылку на первоисточник можно привести?
B>если очень интересно, то я сегодня вечером (после работы) либо завтра сутра
B>поищу повспоминаю откуда я это взял

Не думаю, что твой поиск увенчается успехом.
Re: delete [ ] или delete?
От: Кодт Россия  
Дата: 27.09.05 14:19
Оценка:
Здравствуйте, mavius, Вы писали:

Разные инструкции пользуются разными операторами. Особенно это заметно для классов
struct foo
{
  static void* operator new(size_t n) { return HeapOfSingleObjects::alloc(n); }
  static void operator delete(void* p) { HeapOfSingleObjects::free(p); }

  static void* operator new[](size_t n) { return HeapOfArrays::alloc(n); }
  static void operator delete[](void* p) { HeapOfArrays::free(p); }
};

int main()
{
  // обратите внимание: и конструктор, и деструктор foo тривиальны, поэтому нас это не волнует...
  foo* p = new foo[10]; // HeapOfArrays::alloc(10*sizeof(foo));
  delete p;             // HeapOfSingleObjects::free(p);

В результате имеем шанс расколотить кучу.
Перекуём баги на фичи!
Re[2]: delete [ ] или delete?
От: Кодт Россия  
Дата: 27.09.05 14:25
Оценка:
Кстати говоря, если у класса определены только operator new/operator delete, то new[]/delete[] обратятся не к ним, а к глобальным операторам.
И наоборот, если определены operator new[]/operator delete[], то new/delete одиночного объекта пролетят мимо.
Перекуём баги на фичи!
Re: delete [ ] или delete?
От: WinterMute Россия http://yarrr.ru
Дата: 27.09.05 15:19
Оценка:
Здравствуйте, mavius, Вы писали:

M>Постоянно натыкаюсь на эту непонятку, и, опять же, не понимаю, почему другим это не непонятно

M>// Иногда приходиться создавать динамические массивы, например:

M>
DWORD* a = new DWORD[20];


M>// потом производить хитрые операции,

M>// и, когда этот массив следует удалить,
M>// я всегда поступаю так:

M>
delete a;


M>// А, вот, дядя Страустрап и все остальные мегапрограммеры применяют такую хитрую форму:


M>
delete[] a;


M>// Спрашивается, что нам это даёт и зачем существует в природе?


Кстати, а не синтаксический ли это оверхед? Компилятор ведь сам может определить что стоит справа указатель на элемент, или указатель на массив.
Re[3]: delete [ ] или delete?
От: WinterMute Россия http://yarrr.ru
Дата: 27.09.05 15:28
Оценка:
Здравствуйте, Bell, Вы писали:

B>Здравствуйте, WinterMute, Вы писали:


WM>>Кстати, а не синтаксический ли это оверхед? Компилятор ведь сам может определить что стоит справа указатель на элемент, или указатель на массив.


B>Да ну?



B>
B>extern void my_free(some_struct* ptr);
B>int main()
B>{
B>   my_free(new some_struct());
B>   my_free(new some_struct [10]);

B>   return 0;
B>}

B>//там вдали за рекой
B>void my_free(some_struct* ptr)
B>{
B>   //как тут определить, что есть ptr ?
B>}
B>


А как тут поможет наличие двух операторов delete и delete[]?
Re[4]: delete [ ] или delete?
От: Bell Россия  
Дата: 27.09.05 15:42
Оценка:
Здравствуйте, WinterMute, Вы писали:

WM>А как тут поможет наличие двух операторов delete и delete[]?

Очень просто: для массивов будет вызываться delete[], а для одиночных объектов — delete.
А вот когда что вызывать — вопрос второй. Это может быть к примеру простое соглашение, что мол эта функция используется только для удаления массивов. Можно к примеру передавать дополнительный параметр, но это уже оверхед.
А суть всей проблемы в том, что в С++ типы выражений new int и new int [20] идентичны, и следовательно компилятор тут нам ничем не поможет.
Любите книгу — источник знаний (с) М.Горький
Re[4]: delete [ ] или delete?
От: Кодт Россия  
Дата: 27.09.05 15:49
Оценка:
Здравствуйте, WinterMute, Вы писали:

WM>А как тут поможет наличие двух операторов delete и delete[]?


Конечно, поможет.
void destroy( foo* p, // заметим, что в типе нет информации о том, массив это или одиночный объект
              bool arr
            )
{
  if(arr)
    delete[] p;
  else
    delete p;
}

int main()
{
  destroy( new foo(), false );
  destroy( new foo[123], true );
  destroy( new foo(), true ); // ах, мы что-то перепутали... и уронили себе на ногу
}


Чтобы такого не случалось, можно запретить явное использование new/delete/new[]/delete[], а написать специальные умные указатели двух различных видов — один для одиночных предметов, другой для массивов. И соответствующие производящие функции.

(Это не обязательно boost::scoped_ptr / scoped_array, потому что политика владения — второй вопрос).
Перекуём баги на фичи!
Re[5]: delete [ ] или delete?
От: WinterMute Россия http://yarrr.ru
Дата: 27.09.05 16:09
Оценка:
Здравствуйте, Bell, Вы писали:

B>Здравствуйте, WinterMute, Вы писали:


WM>>А как тут поможет наличие двух операторов delete и delete[]?

B>Очень просто: для массивов будет вызываться delete[], а для одиночных объектов — delete.
B>А вот когда что вызывать — вопрос второй. Это может быть к примеру простое соглашение, что мол эта функция используется только для удаления массивов. Можно к примеру передавать дополнительный параметр, но это уже оверхед.
B>А суть всей проблемы в том, что в С++ типы выражений new int и new int [20] идентичны, и следовательно компилятор тут нам ничем не поможет.

Я, конечно, неправильно выразился, не комплятор знает, а менеджер памяти знает. С той оговоркой, что я не очень хорошо представляю как менеджер памяти работает, я всё-таки предположу как оно всё происходит: если мы пишем delete [] arrPtr, то, компилятор встявляет код, который обращается к менеджеру памяти, чтобы узнать, сколько обектов выделено по этому адресу, для всех них вызываются деструкторы, потом менеджер памяти освобождает этот кусок. Если написать delete arrPtr, то, скорее всего вызовется деструктор только первого объекта, память освободится вся. Т.е., если заставить компилятор всегда смотреть, сколько объектов выделено по этому адресу(эта информация всегда доступна), то можно обойтись одним оператором, разумеется, работать это будет чуть медленнее.

Или я жестоко заблужаюсь?
Re: delete [ ] или delete?
От: nen777w  
Дата: 28.09.05 15:30
Оценка:
для интегральных типов delete[] и delete равноценно.
Posted via RSDN NNTP Server 1.9
Re[2]: delete [ ] или delete?
От: Кодт Россия  
Дата: 28.09.05 15:39
Оценка:
Здравствуйте, nen777w, Вы писали:

N>для интегральных типов delete[] и delete равноценно.


Ссылочку на стандарт, пожалуйста. Или на документацию к компиляторам, где говорится, что данный случай undefined behavior является implementation-defined.
(Как, например, недавно было указано про void* &lt;-&gt; void(*)()
Автор: MaximE
Дата: 25.09.05
)
Перекуём баги на фичи!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.