tom@sco.COM (Tom Kelly) (12/21/90)
In the program below I have an operator delete(void *, size_t) in a base class (base). I derive from that base class, inheriting new and delete. I expect the new and delete operators to be called with the appropriate size of the derived objects. It works fine for operator new(). However, the second argument to operator delete() is always the same, and reflects the size of the base class. According to E&S (ARM), p. 283: If the two argument style is used, operator delete() will be called with a second argument indicating the size of the object being deleted. The size passed is determined by the destructor (if any) or by the (static) type of the pointer being deleted; that is, it will be correct either if the type of the pointer argument to the delete operator is the exact type of the object (and not, for example, just the type of base class) or if the type is that of a base class with a virtual destructor. Since all my deletes are using the exact type of the object, I expect delete to get the right size. Am I mis-interpreting the ARM and doing something wrong, or is this a bug in cfront? If the code ifdef'd with FIX is compiled in, then the program works and gets the expected answer. #include <iostream.h> #include <malloc.h> class base { public: void *operator new(size_t s); void operator delete(void *, size_t); #ifdef FIX virtual ~base() {}; #endif private: int key; }; void * base::operator new(size_t s) { void *p; cout << "calling operator new for base, size " << dec << s << endl; p = malloc(s); cout << "allocated @ " << hex << p << endl; return p; } void base::operator delete(void *p, size_t s) { cout << "called operator delete for base @" << hex << p << dec << " size " << s << endl; free(p); return; } class derived: public base { public: int x; int y; derived(int a, int b): x(a), y(b) {}; }; class derived2: public base { public: int a; char b[10]; }; main() { derived *dp; base *bp; dp = new derived(5, 6); cout << dp->x << " " << dp->y << endl; bp = new base; derived2 *dp2 = new derived2; delete dp; delete dp2; delete bp; } Program Output (compiled -UFIX) calling operator new for base, size 12 allocated @ 0x402aa4 5 6 calling operator new for base, size 4 allocated @ 0x402ab4 calling operator new for base, size 20 allocated @ 0x402abc called operator delete for base @0x402aa4 size 4 called operator delete for base @0x402abc size 4 called operator delete for base @0x402ab4 size 4 Tom Kelly (416) 922-1937 SCO Canada, Inc. (formerly HCR) 130 Bloor St. W., Toronto, Ontario, Canada {utzoo, utcsri, uunet}!scocan!tom or tom@sco.com
mat@mole-end.UUCP (Mark A Terribile) (01/02/91)
In article <1990Dec20.204737.25444@sco.COM>, tom@sco.COM (Tom Kelly) writes: > ... I derive from that base class, inheriting new > and delete. I expect the new and delete operators to be called with > the appropriate size of the derived objects. So far, so good. > It works fine for operator new(). However, the second argument to > operator delete() is always the same, and reflects the size > of the base class. > According to E&S (ARM), p. 283: > ... The size passed ... will be correct either if the > type of the pointer argument to the delete operator is > the exact type of the object (and not, for example, just the > type of base class) or if the type is that of a base class > with a virtual destructor. > Since all my deletes are using the exact type of the object, I expect > delete to get the right size. > Am I mis-interpreting the ARM and doing something wrong, or is this > a bug in cfront? If the code ifdef'd with FIX is compiled in, then > the program works and gets the expected answer. I think you have a bug. If it is any consolation, you probably should use the virtual destructor anyway unless you are very badly cramped for space. It's just plain safer. My own view is that C++ ought to disable SOMETHING when inherited destructors are not virtual. The derived* => base* conversion might be a candidate; so might the availability of operator delete in derived classes. There is a serious weakness in C++ in this area, I think. -- (This man's opinions are his own.) From mole-end Mark Terribile