www.digitalmars.com         C & C++   DMDScript  

c++ - Placement delete not implemented (C++98 5.3.4)

reply Wu Yongwei <Wu_member pathlink.com> writes:
Consider the following program:

-----------------------------------------
#include <stdexcept>
#include <string>
#include <stdio.h>

void* operator new(size_t size, int line)
{
printf("Allocate %u bytes on line %d\n", size, line);
return operator new(size);
}

#ifndef NO_PLACEMENT_DELETE
void operator delete(void* ptr, int line)
{
printf("Placement delete called for object at %p\n", ptr);
operator delete(ptr);
}
#endif

class Obj {
public:
Obj(int n);
private:
int _n;
};

Obj::Obj(int n) : _n(n)
{
if (n == 0) {
throw std::runtime_error("0 not allowed");
}
}

int main()
{
try {
Obj* p = new(__LINE__) Obj(0);
} catch (const std::runtime_error& e) {
printf("Exception: %s\n", e.what());
}
}
-----------------------------------------

Under GCC (2.95.3 and 3.3.1) I got output like:

Allocate 4 bytes on line 36
Placement delete called for object at 00473F28
Exception: 0 not allowed

But with DMC I have compilation problems (using "sc -Ae test.cpp -I
%DMC%\stlport\stlport stlport_dm_static.lib"):

{
^
test.cpp(13) : Error: must be void operator delete(void * [,size_t]);
--- errorlevel 1

But defining NO_PLACEMENT_DELETE will cause a memory leak when an exception
occurs, IN OTHER COMPILERS (e.g. GCC and MSVC).  My tests showed that DMC will
not leak memory and operator delete(size_t) will be implicitly called.  But this
seems not to conform to the C++ standard (ISO/IEC 14882-1998C5.3.4; I just
checked http://www.comnets.rwth-aachen.de/doc/c++std/expr.html#expr.new, Item
18), and is even dangerous if I change l. 40 to

Obj* p = new(existing_buf) Obj(0);

(existing_buf is something like "char existing_buf[1024];".)

In this case, operator delete(size_t) really should not be called, but it IS
now.

Any hope to fix it soon?

Best regards,

Wu Yongwei
Aug 12 2003
next sibling parent "Walter" <walter digitalmars.com> writes:
I'll add it to the bug list. The new/delete support needs to be revamped
anyway, I'll fix it when that gets done.

"Wu Yongwei" <Wu_member pathlink.com> wrote in message
news:bhcamu$2d3g$1 digitaldaemon.com...
 Consider the following program:

 -----------------------------------------
 #include <stdexcept>
 #include <string>
 #include <stdio.h>

 void* operator new(size_t size, int line)
 {
 printf("Allocate %u bytes on line %d\n", size, line);
 return operator new(size);
 }

 #ifndef NO_PLACEMENT_DELETE
 void operator delete(void* ptr, int line)
 {
 printf("Placement delete called for object at %p\n", ptr);
 operator delete(ptr);
 }
 #endif

 class Obj {
 public:
 Obj(int n);
 private:
 int _n;
 };

 Obj::Obj(int n) : _n(n)
 {
 if (n == 0) {
 throw std::runtime_error("0 not allowed");
 }
 }

 int main()
 {
 try {
 Obj* p = new(__LINE__) Obj(0);
 } catch (const std::runtime_error& e) {
 printf("Exception: %s\n", e.what());
 }
 }
 -----------------------------------------

 Under GCC (2.95.3 and 3.3.1) I got output like:

 Allocate 4 bytes on line 36
 Placement delete called for object at 00473F28
 Exception: 0 not allowed

 But with DMC I have compilation problems (using "sc -Ae test.cpp -I
 %DMC%\stlport\stlport stlport_dm_static.lib"):

 {
 ^
 test.cpp(13) : Error: must be void operator delete(void * [,size_t]);
 --- errorlevel 1

 But defining NO_PLACEMENT_DELETE will cause a memory leak when an
exception
 occurs, IN OTHER COMPILERS (e.g. GCC and MSVC).  My tests showed that DMC
will
 not leak memory and operator delete(size_t) will be implicitly called.
But this
 seems not to conform to the C++ standard (ISO/IEC 14882-1998C5.3.4; I
just
 checked http://www.comnets.rwth-aachen.de/doc/c++std/expr.html#expr.new,
Item
 18), and is even dangerous if I change l. 40 to

 Obj* p = new(existing_buf) Obj(0);

 (existing_buf is something like "char existing_buf[1024];".)

 In this case, operator delete(size_t) really should not be called, but it
IS
 now.

 Any hope to fix it soon?

 Best regards,

 Wu Yongwei
Aug 13 2003
prev sibling parent "Michele" <noways aliceposta.it> writes:
also i'm having problems on dmc 8.3.5n with placement delete and new/delete
resolution:

#include <stdio.h>
#include <conio.h>
#include <stdlib.h>

//the allocator must know the size of chunks from address!!
class iallocator
{
 public:
 virtual void* alloc(size_t s)
 {
  void* tmp = malloc(s);
  printf("allocator::alloc(%d) return:%x\n",s,tmp);
  return tmp;
 }
 virtual void free(void* p)
 {
  printf("allocator::free(addr:%x)\n",p);
  ::free(p);
 }
 virtual void* reserve(size_t s)
 {
  return NULL;
 }
};

iallocator globalallocator;
#define GLOBAL_ALLOCATOR globalallocator

void* operator new(size_t s)
{
 printf("::new(%d)\n",s);
 return NULL;
}
void operator delete(void* p)
{
 printf("::delete()\n");
}

class base
{
 public:
 base()
 {
  //NOP
 }

 ~base()
 {
  //NOP
 }

 inline static void* New(size_t s,iallocator &allo = GLOBAL_ALLOCATOR)
 {
  void** pchunk = (void**) allo.alloc(s+sizeof(void*));
  pchunk[0] = (void*)&allo;
  return &pchunk[1];
 }

 inline static void Delete(void* p,iallocator &allo)
 {
  allo.free(&((void**)p)[-1]);
 }

 inline static void Delete(void* p)
 {
  iallocator* allo = (iallocator*)((void**)p)[-1];
  allo->free(&((void**)p)[-1]);
 }

 void* operator new(size_t s)
 {
  printf("base::new(size:%d)\n",s);
  return New(s);
 }

 void operator delete(void* p,size_t s)
 {
  printf("base::delete(addr:%x)\n",p);
  Delete(p);
 }

//also this new operator should give a compiler error because the
correspondig delete is undeclarable
//and if exception are enabled the compiler need the corresponding delete in
case of exception in ctor
 void* operator new(size_t s,iallocator &allo)
 {
  printf("base::new(size:%d,allocator:%x)\n",s,&allo);
  return New(s,allo);
 }
/* compiler error because no placement delete supported
 void operator delete(void* p,size_t s,iallocator &allo)
 {
  printf("base::delete(addr:%x,allocator:%x)\n",p,&allo);
  Delete(p,allo);
 }
*/
 void* operator new[](size_t s)
 {
  printf("base::new[](size:%d)\n",s);
  return New(s);
 }

 void operator delete[](void* p,size_t s)
 {
  printf("base::delete[](addr:%x)\n",p);
  Delete(p);
 }

// same for the operator new[]
 void* operator new[](size_t s,iallocator &allo)
 {
  printf("base::new[](size:%d,allocator:%x)\n",s,&allo);
  return New(s,allo);
 }
/* compiler error because no placement delete[] supported
 void operator delete[](void* p,iallocator &allo)
 {
  printf("base::delete[](addr:%x,allocator:%x)\n",p,&allo);
  Delete(p,allo);
 }
*/
};

//**************************************************************************
****

class a : public base
{
 private:
 int _a;
 public:
 a()
 {
  printf("a::ctor()\n");
  //throw 1;
 }

 a(int p)
 {
  printf("a::ctor(%d)\n",p);
  _a = 666;
  if(p)
   throw 1;
 }
 ~a()
 {
  printf("a::dtor()\n");
 }
};

int main(int argc, char *argv[])
{
 a* poa;

 try
 {
  poa = new a(1);
  delete poa;
 }
 catch(int ignore)
 {}

 printf("\n");

 poa = new a(0);
 delete poa;

 printf("\n");

 try
 {
  poa = new(globalallocator) a(1);
  delete poa;
 }
 catch(int ignore)
 {}

 printf("\n");

 poa = new(globalallocator) a(0);
 delete poa;

 printf("\n");

 try
 {
  poa = new a[3];
  delete[] poa;
 }
 catch(int ignore)
 {}

 printf("\n");

 try
 {
  poa = new(globalallocator) a[3];
  delete[] poa;
 }
 catch(int ignore)
 {}

 getchar();
 return 0;
}


compiled with: dmc -Ae

also the output have somethig strage:

OUTPUT:

base::new(size:4)
allocator::alloc(8) return:8303d0
a::ctor(1)
base::delete(addr:8303d4) //expected call to placement delete
allocator::free(addr:8303d0)

base::new(size:4)
allocator::alloc(8) return:8303d0
a::ctor(0)
a::dtor()
base::delete(addr:8303d4)
allocator::free(addr:8303d0)

base::new(size:4,allocator:40bf2c)
allocator::alloc(8) return:8303d0
a::ctor(1)
base::delete(addr:8303d4)
allocator::free(addr:8303d0)

base::new(size:4,allocator:40bf2c)
allocator::alloc(8) return:8303d0
a::ctor(0)
a::dtor()
base::delete(addr:8303d4)
allocator::free(addr:8303d0)

a::ctor()        //???? new is't called? after the first ctor i'll expect
base::new[] as in the next section
a::ctor()
a::ctor()
a::dtor()
a::dtor()
a::dtor()
::delete() //called global delete??? i think should be: base::delete[]

base::new[](size:16,allocator:40bf2c)
allocator::alloc(20) return:830da8
a::ctor()
a::ctor()
a::ctor()
a::dtor()
a::dtor()
a::dtor()
::delete() //called global delete??? i think should be: placement
base::delete[]
Sep 07 2003