c++ - Placement delete not implemented (C++98 5.3.4)
- Wu Yongwei (61/61) Aug 12 2003 Consider the following program:
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
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 anexceptionoccurs, IN OTHER COMPILERS (e.g. GCC and MSVC). My tests showed that DMCwillnot leak memory and operator delete(size_t) will be implicitly called.But thisseems not to conform to the C++ standard (ISO/IEC 14882-1998C5.3.4; Ijustchecked http://www.comnets.rwth-aachen.de/doc/c++std/expr.html#expr.new,Item18), 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 itISnow. Any hope to fix it soon? Best regards, Wu Yongwei
Aug 13 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[]
Sep 07 2003