Размещающий оператор new
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 02.12.05 06:11
Оценка:
Сегодня ночью сделал очередное страшной открытие

Компилятор (мучался BCB5) распознает размещающий оператор new и не вызывает оператор delete, если конструктор класса сгенерирует исключение. То есть конструкции вида
T::T()//throw
{
 throw runtime_error("test")
}

void* T::operator new(size_t /*sz*/,void* pv)
{
 return pv;
}

void T::operator delete(void* pv) //не вызывается
{
 free_memory(pv);
}

//.....
T* const x=new(allocate_memory(sizeof(T))) T();//throw

будут приводить к утечке памяти. И хотя это абсолютно логично, все равно — натуральная измена
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re: Размещающий оператор new
От: Владислав Сомов http://forum.sukhoi.ru/forumdisplay.php?f=120
Дата: 02.12.05 06:25
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>Сегодня ночью сделал очередное страшной открытие


КД>Компилятор (мучался BCB5) распознает размещающий оператор new и не вызывает оператор delete, если конструктор класса сгенерирует исключение. То есть конструкции вида

КД>
КД>T::T()//throw
КД>{
КД> throw runtime_error("test")
КД>}

КД>void* T::operator new(size_t /*sz*/,void* pv)
КД>{
КД> return pv;
КД>}

КД>void T::operator delete(void* pv) //не вызывается
КД>{
КД> free_memory(pv);
КД>}

КД>//.....
КД>T* const x=new(allocate_memory(sizeof(T))) T();//throw
КД>

КД>будут приводить к утечке памяти. И хотя это абсолютно логично, все равно — натуральная измена

Я бы порадовался такому открытию :o).
Re: Размещающий оператор new
От: Erop Россия  
Дата: 02.12.05 07:56
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:

    T* const x=new(allocate_memory(sizeof(T))) T();//throw

КД>будут приводить к утечке памяти. И хотя это абсолютно логично, все равно — натуральная измена

А что бы ты хотел?
Вот, скажем, такой код:
    allocate_memory(sizeof(T));
    T();

тебя не парит?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: Размещающий оператор new
От: Шахтер Интернет  
Дата: 02.12.05 08:19
Оценка: +3
Здравствуйте, Коваленко Дмитрий, Вы писали:

Операторы new и delete ходят парами. Вот правильная пара.

void T::operator delete(void *,void* pv)
 {
  ...
 }
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[2]: Размещающий оператор new
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 02.12.05 08:36
Оценка:
Здравствуйте, Шахтер, Вы писали:

Ш>Операторы new и delete ходят парами. Вот правильная пара.


Ш>void T::operator delete(void *,void* pv)
Ш> {
Ш>  ...
Ш> }


Я думаю, что ты не прав.

Более того, BCB5 такие пары не парят — он просто не понимает операторы delete отличные от
void delete(void*);
void delete(void*,size_t);

и требует для класса только одно определение оператора delete
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re[3]: Размещающий оператор new
От: Шахтер Интернет  
Дата: 02.12.05 08:44
Оценка: +4 :)
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>Здравствуйте, Шахтер, Вы писали:


Ш>>Операторы new и delete ходят парами. Вот правильная пара.


КД>
Ш>>void T::operator delete(void *,void* pv)
Ш>> {
Ш>>  ...
Ш>> }
КД>


КД>Я думаю, что ты не прав.


Я прав. Читай стандарт. Парный delete должен вызываться при исключениях.
Иначе это не C++, а какой-то другой язык.

КД>Более того, BCB5 такие пары не парят — он просто не понимает операторы delete отличные от

КД>
КД>void delete(void*);
КД>void delete(void*,size_t);
КД>

КД>и требует для класса только одно определение оператора delete

Это личное горе людей, использующих убогие компиляторы.
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[3]: Размещающий оператор new
От: ArtDenis Россия  
Дата: 02.12.05 08:46
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>Более того, BCB5 такие пары не парят — он просто не понимает операторы delete отличные от

КД>
КД>void delete(void*);
КД>void delete(void*,size_t);
КД>

КД>и требует для класса только одно определение оператора delete

А
#include <new>

точно сделал перед использованием этих операторов?
... << RSDN@Home 1.1.4 stable rev. 510>>
[ 🎯 Дартс-лига Уфы | 🌙 Программа для сложения астрофото ]
Re[3]: Размещающий оператор new
От: Lorenzo_LAMAS  
Дата: 02.12.05 09:21
Оценка: :)))
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>Здравствуйте, Шахтер, Вы писали:


Ш>>Операторы new и delete ходят парами. Вот правильная пара.


КД>
Ш>>void T::operator delete(void *,void* pv)
Ш>> {
Ш>>  ...
Ш>> }
КД>


КД>Я думаю, что ты не прав.


А я думаю, он прав.
Of course, the code must be complete enough to compile and link.
Re[4]: Размещающий оператор new
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 02.12.05 09:31
Оценка:
Здравствуйте, Шахтер, Вы писали:

Ш>>>Операторы new и delete ходят парами. Вот правильная пара.


Ш>>>void T::operator delete(void *,void* pv)
Ш>>> {
Ш>>>  ...
Ш>>> }


КД>>Я думаю, что ты не прав.


Ш>Я прав. Читай стандарт. Парный delete должен вызываться при исключениях.


Я все равно не догнал — какой толк от delete в таком виде, если для размещающего оператора new он все равно не вызывется?

Да, кстати. Вот в этой
Автор: Алексей Кирюшкин
Дата: 11.11.05
книжке, размещающий оператор new обозначен как исключение из этого правила.

КД>>Более того, BCB5 такие пары не парят — он просто не понимает операторы delete отличные от


Ш>Это личное горе людей, использующих убогие компиляторы.


О да, конечно. Спасибо, что лишний раз напомнили.
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re[5]: Размещающий оператор new
От: Lorenzo_LAMAS  
Дата: 02.12.05 10:44
Оценка: 10 (1) +1
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>Здравствуйте, Шахтер, Вы писали:


Ш>>>>Операторы new и delete ходят парами. Вот правильная пара.


КД>
Ш>>>>void T::operator delete(void *,void* pv)
Ш>>>> {
Ш>>>>  ...
Ш>>>> }
КД>


КД>>>Я думаю, что ты не прав.


Ш>>Я прав. Читай стандарт. Парный delete должен вызываться при исключениях.


КД>Я все равно не догнал — какой толк от delete в таком виде, если для размещающего оператора new он все равно не вызывется?


Как какой? Такой — есть у тебя перегруженный для класса void *operator new(std::size_t, void *); и есть парный ему оператор
void operator delete(void *, void *); Если в конструкторе (вызванном из new-expression, в котором использовался new с синтаксисом размещения и вызовом твоего оператора new(size_t, void *)) возникло исключение, то будет вызван (помимо всего прочего) парный operator delete. Не знаю, может у борланда и не вызовется. Кстати, по этому поводу с доисторических времен VC умел выдавать ворнинг в случае отсутствия парных операторов.

КД>Да, кстати. Вот в этой
Автор: Алексей Кирюшкин
Дата: 11.11.05
книжке, размещающий оператор new обозначен как исключение из этого правила.


Нельзя ли цитату?
Of course, the code must be complete enough to compile and link.
Re: Размещающий оператор new
От: programmater  
Дата: 02.12.05 11:23
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>Сегодня ночью сделал очередное страшной открытие


КД>Компилятор (мучался BCB5) распознает размещающий оператор new и не вызывает оператор delete, если конструктор класса сгенерирует исключение.


Дык и не должен . Передо мной лежит Страуструп "Язык программирования С++. Специальное издание" 2005 года, читаем параграф 10.4.11 "Размещение объектов" стр 304:
"Помещение объекта в память, которая (непосредственно) не управляется стандартным распределителем сводбодной памяти подразумевает определенные действия при уничтожении объекта. Базовым механизмом для этого является явный вызов деструктора:
  void destroy(X* p, Arena* a)
  {
     p->~X();
     a->free();
  }

" Конец циататы.
Так в чем компилятор не прав? Тебе же сказали явный вызов деструктора! Так что ты от компилятора хочешь?
Re[6]: Размещающий оператор new
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 02.12.05 11:36
Оценка:
Здравствуйте, Lorenzo_LAMAS, Вы писали:

КД>>Я все равно не догнал — какой толк от delete в таком виде, если для размещающего оператора new он все равно не вызывется?


L_L>Как какой? Такой — есть у тебя перегруженный для класса void *operator new(std::size_t, void *); и есть парный ему оператор

L_L>void operator delete(void *, void *); Если в конструкторе (вызванном из new-expression, в котором использовался new с синтаксисом размещения и вызовом твоего оператора new(size_t, void *)) возникло исключение, то будет вызван (помимо всего прочего) парный operator delete

Спасибо.

////////////////////////////////////////////////////////////////////////////////
//class T1

class T1
{
 public:
  T1()
  {
   cout<<"T1:T1"<<endl;

   throw runtime_error("test");
  }

 ~T1()
  {
   cout<<"T1:~T1"<<endl;
  }

  static void* operator new (size_t sz,void* pv)
  {
   cout<<"T1:operator new(sz,pv)"<<endl;
   return pv;
  }

  static void operator delete (void* pv)
  {
   cout<<"T1:operator delete(pv)"<<endl;
  }

 #ifndef __BORLANDC__
  //BCB5: [C++ Error] main.cpp(20):
  // E2193 Too few parameters in call to 'T1::operator delete(void *,void *)'
  static void operator delete (void* pv,void* pv2)
  {
   cout<<"T1:operator delete(pv,pv2)"<<endl;
  }
 #endif 
};//class T1

////////////////////////////////////////////////////////////////////////////////
//main

int main(int /*argc*/,char* /*argv*/[])
{
 try
 {
  new(reinterpret_cast<T1*>(0)+1) T1();
 }
 catch(const exception& e)
 {
  cout<<"exception: "<<e.what()<<endl;
 }
 catch(...)
 {
  cout<<"exception: ..."<<endl;
 }

 return 0;
}//main

В VC7 выводится
T1:operator new(sz,pv)
T1:T1
T1:operator delete(pv,pv2)
exception: test

Фантастика!

>Не знаю, может у борланда и не вызовется.


Он у него просто не компилируется

КД>>Да, кстати. Вот в этой
Автор: Алексей Кирюшкин
Дата: 11.11.05
книжке, размещающий оператор new обозначен как исключение из этого правила.


L_L>Нельзя ли цитату?


Книги под рукой нет. В конце 45 правила — исключения из правил. Общий смысл, который понял я — считается, что размещающий оператор new по-определению не занимается выделением памяти, поэтому парный delete ему не нужен.

Тем не менее, когда я закоментировал delete(void*,void*) VC7 выдал
e:\Users\Dima\Work\TestCode\compiler_test\test_008\main.cpp(55):
 warning C4291: 'void *T1::operator new(size_t,void *)' :
  no matching operator delete found;
   memory will not be freed if initialization throws an exception

Так что теперь буду ломать голову — как спроектировать код, который бы понравился всем ... хотя да, конечно, __BORLANDC__ нам поможет
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re[2]: Размещающий оператор new
От: Lorenzo_LAMAS  
Дата: 02.12.05 11:37
Оценка:
P> Так в чем компилятор не прав? Тебе же сказали явный вызов деструктора! Так что ты от компилятора хочешь?

Автор говорит о другой ситуации, о возникновении исключения в new-expression, когда ты не сможешь вызывать деструкторов и функций и когда за тебя это сделает код, сгенеренный компилятором.
Кстати, как здесь уже обсуждалось, в С++ имеется какая-то асимметрия с placement-new, создавая объект при его помощи, разрушать приходится несимметричным корявым способом
Of course, the code must be complete enough to compile and link.
Re[7]: Размещающий оператор new
От: Lorenzo_LAMAS  
Дата: 02.12.05 11:40
Оценка:
Т.е. BCC даже не может правильно понять, что это за конструкция?
Of course, the code must be complete enough to compile and link.
Re[8]: Размещающий оператор new
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 02.12.05 11:42
Оценка:
Здравствуйте, Lorenzo_LAMAS, Вы писали:

L_L>Т.е. BCC даже не может правильно понять, что это за конструкция?


Да. Но я все равно его не брошу — потому что он хороший
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re[4]: Размещающий оператор new
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 02.12.05 11:45
Оценка:
Здравствуйте, ArtDenis, Вы писали:

КД>>Более того, BCB5 такие пары не парят — он просто не понимает операторы delete отличные от

КД>>void delete(void*);
КД>>void delete(void*,size_t);

КД>>и требует для класса только одно определение оператора delete

AD>А

AD>#include <new>

AD>точно сделал перед использованием этих операторов?

А что это должно дать?
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re[9]: Размещающий оператор new
От: Lorenzo_LAMAS  
Дата: 02.12.05 11:56
Оценка:
КД>Да. Но я все равно его не брошу — потому что он хороший

Дождись их BCB 2006 Или как там его?
Of course, the code must be complete enough to compile and link.
Re[10]: Размещающий оператор new
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 02.12.05 12:09
Оценка:
Здравствуйте, Lorenzo_LAMAS, Вы писали:

КД>>Да. Но я все равно его не брошу — потому что он хороший


L_L>Дождись их BCB 2006 Или как там его?


Да ладно, так и говори — Delphi 2006
На сколько я понял, эти свиномордии там оставили компилятор на уровне BCB6. Который, на мой взгляд, хуже чем BCB5
Хочется надеяться, что я заблуждаюсь — наш заказчик вроде заказал коробку этой студии — буду писать по-настоящему интересные программы
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re[11]: Размещающий оператор new
От: Lorenzo_LAMAS  
Дата: 02.12.05 12:16
Оценка:
КД>Да ладно, так и говори — Delphi 2006

Они вроде как по аналогии с VS теперь хотят иметь одну ИДЕ для Дельфи, С++ и С#

КД>На сколько я понял, эти свиномордии там оставили компилятор на уровне BCB6. Который, на мой взгляд, хуже чем BCB5


Интересно. В C Builder X года 1.5-2 назад у них был экспериментальный компилятор, использующий ЕДГ фронт-энд (и даже поддержка экспорта шаблонов была, хоть и работало все как-то криво-криво). Что же они, забили на него? Зачем бабло платили?
Of course, the code must be complete enough to compile and link.
Re[5]: Размещающий оператор new
От: ArtDenis Россия  
Дата: 02.12.05 12:20
Оценка:
КД>А что это должно дать?

Ничего. Просто я опять написал ответ в торопях, даже не вдавшись в суть вопроса
... << RSDN@Home 1.1.4 stable rev. 510>>
[ 🎯 Дартс-лига Уфы | 🌙 Программа для сложения астрофото ]
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.