Thread overview
Placement delete not implemented (C++98 5.3.4)
Aug 13, 2003
Wu Yongwei
Aug 13, 2003
Walter
Sep 07, 2003
Michele
August 13, 2003
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-1998C5.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


August 13, 2003
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-1998C5.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
>
>


September 07, 2003
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[]