Thread View: comp.std.c++
2 messages
2 total messages
Started by mike
Fri, 12 Jan 1996 17:20
Overloading 'operator new': errors in MSVC 2.0 or not?
Author: mike
Date: Fri, 12 Jan 1996 17:20
Date: Fri, 12 Jan 1996 17:20
77 lines
2854 bytes
2854 bytes
I think I've discovered some errors in Microsoft Visual C++ 2.0 compiler.
1) Suppose we want to overload global 'operator new':
void* operator new (size_t size, MemoryAllocator* palloc)
{
// Allocate memory using special allocator
return palloc->alloc (size);
}
How to delete object allocated by this function?
We can't overload 'operator delete' (according to ARM 5.3.4, 12.5).
We must write something like this:
void Delete_SomeClass (SomeClass* p, MemoryAllocator* palloc)
{
p->~SomeClass (); // direct destructor call
palloc->free (p); // free memory
}
It works, but it is too tiresome to write such function for every class.
A better way is to use template function:
template <class Type>
void Delete (Type* p, MemoryAllocator* palloc)
{
p->~Type (); // direct destructor call - is it allowed here?
palloc->free (p); // free memory
}
But if I try to write
MemoryAllocator alloc;
SomeClass* p = new (&alloc) SomeClass;
Delete (p, &alloc);
then compiler writes something like
filename(line#) : error C2300: 'SomeClass' : class does
not have a destructor called '~Type'
Is it an error of compiler? Or direct call of destructor
in template is not allowed? I haven't found something
about it in ARM.
2) Again, let's overload global 'operator new' with default parameter:
void* operator new (size_t size, MemoryAllocator* palloc = NULL)
{
return palloc ? palloc->alloc (size) : malloc (size);
}
If I write now
char* p = new char [100];
then compiler (it seems) must invoke operator new (100, NULL). But when I've
inspected assembler listing, I discovered that compiler invokes standard
library version of 'operator new' rather than overloaded one.
To correct it, I have to write
void* operator new (size_t size, MemoryAllocator* palloc)
{
return palloc ? palloc->alloc (size) : malloc (size);
}
void* operator new (size_t size)
{
return operator new (size, NULL);
}
Now it works OK. Is it also a compiler error?
Alex Bobkov.
---
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. The moderation policy
is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Re: Overloading 'operator new': errors in MSVC 2.0 or not?
Author: Fergus Henderson
Date: Sat, 13 Jan 1996 00:56
Date: Sat, 13 Jan 1996 00:56
135 lines
5475 bytes
5475 bytes
mike <mike@redline.ru> writes:
>I think I've discovered some errors in Microsoft Visual C++ 2.0 compiler.
>
>1) Suppose we want to overload global 'operator new':
>
>void* operator new (size_t size, MemoryAllocator* palloc)
>{
> // Allocate memory using special allocator
> return palloc->alloc (size);
>}
>
>How to delete object allocated by this function?
>We can't overload 'operator delete' (according to ARM 5.3.4, 12.5).
The ARM is out-of-date on this one; the committee has changed things so
you are indeed allowed to overload operator delete. This is basically
just for specifying cleanup if an exception is thrown, since there is
no nice syntax for invoking the destructor and the overloaded operator
delete. To ensure that you do get correct cleanup in an expression such
as `new (palloc) Foo' if the `Foo::Foo()' constructor throws an exception,
you should define an appropriate overloaded operator delete:
void* operator delete (void *p, MemoryAllocator* palloc)
{
palloc->free (p); // free memory
}
>We must write something like this:
>
>void Delete_SomeClass (SomeClass* p, MemoryAllocator* palloc)
>{
> p->~SomeClass (); // direct destructor call
> palloc->free (p); // free memory
>}
Yep, you will still need this, even if you overload operator delete
as above; the syntax `delete (palloc) p' will not work.
>It works, but it is too tiresome to write such function for every class.
>A better way is to use template function:
>
>template <class Type>
>void Delete (Type* p, MemoryAllocator* palloc)
>{
> p->~Type (); // direct destructor call - is it allowed here?
> palloc->free (p); // free memory
>}
Yes, the direct destructor call is allowed.
>But if I try to write
>
> MemoryAllocator alloc;
> SomeClass* p = new (&alloc) SomeClass;
> Delete (p, &alloc);
>
>then compiler writes something like
>filename(line#) : error C2300: 'SomeClass' : class does
>not have a destructor called '~Type'
>
>Is it an error of compiler?
Yes, your code is fine - you need to get a better compiler.
>2) Again, let's overload global 'operator new' with default parameter:
>
>void* operator new (size_t size, MemoryAllocator* palloc = NULL)
>{
> return palloc ? palloc->alloc (size) : malloc (size);
>}
That is not correct, since it won't do the right thing for zero-sized
allocations. You should write
void* operator new (size_t size, MemoryAllocator* palloc = NULL)
{
return palloc ? palloc->alloc (size) : malloc (size == 0 ? 1 : size);
} ^^^^^^^^^^^^^^^^^^^^
to make sure that you return a distinct address for each zero-sized
allocation.
Also, the use of a default parameter probably doesn't do what you want.
Rather than replacing the built-in global `operator new(size_t)', the
two versions will coexist. The September 95 draft standard says
(see 5.3.4 [expr.new]) that in an expression like `new int', the
"appropriate" allocation function will be called, but in this case it
is not clear which allocation function is appropriate. A compiler
might always call the global `operator new(size_t)' rather than your
version. Or it might try to perform overload resolution, which would
mean that if you #include <new.h>, which declares the global `operator
new(size_t)', then any expression like `new int' will result in an
ambiguity error. Or it might consider such expressions ambiguous even
if you don't #include <new.h>.
>If I write now
>
> char* p = new char [100];
>
>then compiler (it seems) must invoke operator new (100, NULL). But when I've
>inspected assembler listing, I discovered that compiler invokes standard
>library version of 'operator new' rather than overloaded one.
>To correct it, I have to write
>
>void* operator new (size_t size, MemoryAllocator* palloc)
>{
> return palloc ? palloc->alloc (size) : malloc (size);
>}
>void* operator new (size_t size)
>{
> return operator new (size, NULL);
>}
>
>Now it works OK. Is it also a compiler error?
No. For
char* p = new char [100];
the compiler should invoke `operator new [] (size_t)' rather than
`operator new (size_t)'. The default behaviour of `operator new [] (size_t)'
is to invoke `operator new (size_t)'. This explains what you are seeing.
Anyhow, defining a (possibly inline) `operator new (size_t)' is a much
better idea than using a default operator, because it avoids the possible
problems I mentioned above.
--
Fergus Henderson WWW: http://www.cs.mu.oz.au/~fjh
fjh@cs.mu.oz.au PGP: finger fjh@128.250.37.3
---
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. The moderation policy
is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads