Topic: Overloaded new/delete


Author: "Alan Gray" <agray@oznet02.ozemail.com.au>
Date: 1995/11/25
Raw View
Given

class Malloc {
public:
  void *allocate(size_t sz);
  void  deallocate(void *ptr);
};

void *operator new(size_t sz,Malloc *myalloc)
{
  return(myalloc->allocate(sz));
}
void operator delete(void *ptr,Malloc *myalloc)  // new in WP ??
{
  myalloc->deallocate(ptr);
}

class Base {
public:
  Base();
  virtual ~Base();
};

class Derived : public Base {
public:
  Derived();
 ~Derived();
};

void fred(Malloc *myalloc)
{
  double *a = new(myalloc) double[1024];
  double *b = new(myalloc) double;
  Base   *c = new(myalloc) Derived[1024];
  Base   *d = new(myalloc) Derived;

...   lots of code

// HOW do i free a,b,c & d so that
// (1) all the destructors are called
// (2) the memory is deallocated

  delete(myalloc) [] a;         // not C++
  delete(myalloc)    b;         // not C++
  delete(myalloc) [] c;         // not C++
  delete(myalloc)    d;         // not C++

// call manually

  ::operator delete(a,myalloc);
  ::operator delete(b,myalloc);

// will this call the destructor for the 1024 Derived elements created
// & deallocate all the memory

  ::operator delete(c,myalloc);

// will this call the destructor for the 1 Derived element created
// & deallocate all the memory

  ::operator delete(d,myalloc);
}

Other questions this code raises is

(1)

Will size_t sz passed to new(size_t sz,Malloc *mymalloc)
include the overhead for the number of objects allocated ??
and will the compiler adjust the retured pointer so that
a,b,c & d point to the start of array, not at the number of objects ?

(P.S) Microsoft Visual C++ 2.0 works OK here

(2)

How can the compiler known that c was an array of objects allocated,
especially if c is deleted in a different compilation unit.
Is there a specific syntax for this.

I'm guessing but, do I need to declare

void *operator new[](size_t sz,Malloc *myalloc) &
void *operator delete[](size_t sz,Malloc *myalloc)

Alan Gray
4D Solutions PTY LTD

PO BOX 103 Narrabeen NSW
2101 Australia

agray@ozemail.com.au
---
[ 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. ]





Author: fjh@munta.cs.mu.OZ.AU (Fergus Henderson)
Date: 1995/11/26
Raw View
"Alan Gray" <agray@oznet02.ozemail.com.au> writes:

>Given
>
>void *operator new(size_t sz,Malloc *myalloc)
...
>void operator delete(void *ptr,Malloc *myalloc)  // new in WP ??
...
>void fred(Malloc *myalloc)
>{
>  double *a = new(myalloc) double[1024];
>  double *b = new(myalloc) double;
>  Base   *c = new(myalloc) Derived[1024];
>  Base   *d = new(myalloc) Derived;
...
>// HOW do i free a,b,c & d so that
>// (1) all the destructors are called
>// (2) the memory is deallocated

You can clean up `b' and `d' like this:

 Delete(b);
 Delete(d);

That assumes the following definition of Delete():

 template <class T>
 void Delete (const T *ptr, Malloc *myalloc)
 {
  ptr->~T();
  ::operator delete (myalloc, ptr);
 }

Unfortunately, using a similar technique for `a' is not guaranteed to
work:

 template <class T>
 void DeleteArray (const T *ptr, Malloc *myalloc, size_t size)
 {
  for (size_t i = 0; i < size; i++) {
   ptr[i].~T();
  }
  ::operator delete [] (myalloc, ptr);
 }

 DeleteArray(a);

The reason this may not work is that the value returned by

 new (myalloc) double[1024]

may not be the same as the value returned from

 operator new (myalloc, size)

since the implementation may allocate extra space for a count
of the number of elements.  There is no guarantee that the pointer
you pass to ::operator delete [] () points to a value that
was allocated with ::operator new [] ().

So as far as I can tell, for `a' and `c', you are SOL.

For `c', you were already in a bad shape anyway - an
expression like `c[1]' would be undefined behaviour,
and you would have had to use

 DeleteArray(dynamic_cast<Derived *>(c));

to deallocate the memory (but of course that doesn't solve
the above-mentioned problem).  Basically, even though
a Derived IS-A Base, an array of Derived IS-NOT-AN array of Base.

>// will this call the destructor for the 1024 Derived elements created
>// & deallocate all the memory
>
>  ::operator delete(c,myalloc);

No, it won't call the destructor.

>// will this call the destructor for the 1 Derived element created
>// & deallocate all the memory
>
>  ::operator delete(d,myalloc);

It won't call the destructor - if you call the deallocation function manually,
then you have to call the destructor manually too.
But it will deallocate all the memory.

>}
>
>Other questions this code raises is
>
>(1)
>
>Will size_t sz passed to new(size_t sz,Malloc *mymalloc)
>include the overhead for the number of objects allocated ??

The answer is "maybe" - it is up to the implementation.
Typically the answer will be "no" unless the object has a (non-trivial)
destructor, in which case it will be "yes".

>I'm guessing but, do I need to declare
>
>void *operator new[](size_t sz,Malloc *myalloc) &
>void *operator delete[](size_t sz,Malloc *myalloc)

Yes, that would be a good idea.  But it still doesn't solve the
problem.  You are still SOL.  I think this is a quite severe problem
with the current draft standard.

--
Fergus Henderson              WWW: http://www.cs.mu.oz.au/~fjh
fjh@cs.mu.oz.au               PGP: finger fjh@128.250.37.3
I will have little or no net access from Nov 30 until Dec 25.
Please email me a copy of any follow-ups.
---
[ 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. ]





Author: fjh@munta.cs.mu.OZ.AU (Fergus Henderson)
Date: 1995/11/27
Raw View
Oops, I made a couple of mistakes in my previous post:

>You can clean up `b' and `d' like this:
>
> Delete(b);
> Delete(d);

That should be

 Delete(b, myalloc);
 Delete(d, myalloc);

> DeleteArray(a);

That should be

 DeleteArray(a, myalloc, 1024);

Apologies for any confusion that caused.

--
Fergus Henderson              WWW: http://www.cs.mu.oz.au/~fjh
fjh@cs.mu.oz.au               PGP: finger fjh@128.250.37.3
I will have little or no net access from Nov 30 until Dec 25.
Please email me a copy of any follow-ups.

[ 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. ]