Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
Home
Discussion Groups
General
GeneralPortable MacsHardwareNetworking
Applications
Mac ApplicationsEudoraFirefox / MozillaInternet ExplorerOutlook ExpressMS OfficeEntourageExcelPowerPointWordVirtual PCMedia PlayerOther MS Products
Programming
Mac ProgrammingCodeWarriorPerl
Country Specific
Australian Mac GroupUK Mac Group

Mac Forum / Programming / CodeWarrior / July 2004



Tip: Looking for answers? Try searching our database.

operator delete[] woes

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Macs 4 Sale - 23 Jul 2004 04:49 GMT
Hi All -

I have a rather nasty problem regarding operator delete[] and CW 9.2.
Calling delete[] on an object that was allocated with new[] but is then
POINTED to by the object's superclass results in only 1 virtual dtor
being called. This is a little tricky to explain, so maybe a simple
test program will clarify:

#include <iostream>
using namespace std;

class foo
{
public:
  virtual ~foo() { cout << "foo dtor\n"; }
};

class bar : public foo
{
public:
  virtual ~bar() { cout << "bar dtor\n"; }
};

int main()
{
  using namespace std;
 
  // This first example results in expected behavior.
  // The delete operator calls bar's dtor, which then in turn
  // calls foo's dtor.
  foo *f = new bar;
  delete( f );

  cout << "--------\n";

  // Again, expected behavior.
  // The delete[] operator calls bar's dtor, which then in turn
  // calls foo's dtor.
  bar *b = new bar[1];
  delete [] b;

  cout << "--------\n";

  // Badness!
  // The delete[] operator does not call bar's dtor. Instead,
  // the CW compiler always uses foo's dtor when calling
  // __destroy_new_array.  Can this be fixed?
  foo *foobar = new bar[1];
  delete [] foobar;
 
  return 0;
}

Sample output:

bar dtor
foo dtor
-------
bar dtor
foo dtor
-------
foo dtor

In the above example, regular new/delete work as expected -- both dtors
are called as expected. But new[]/delete[] only works if the CW
compiler KNOWS it's delete[]'ing an object of type "bar". Otherwise,
foo's dtor is mistakenly called. A quick disassembly of the code
revealed that the CW compiler is passing __destroy_new_array a pointer
to foo's dtor. I cannot figure out a way to make the compiler know to
use bar's dtor (like with using regular new/delete).

I kind of blundered into this problem while tracking down some other
memory leaks. Needless to say, I was shocked to find my app leaking a
LOT of memory. Unfortunately, this is a Mac port of a 500,000 line
MSVC++ program, and I can't easily re-engineer the codebase without
making massive changes. BTW, trying this test code on MSVC++ results in
expected behavior -- delete[] always calls bar's dtor on my PC. I guess
that's why the original PC program didn't leak memory so much;-)

Anyway, any help y'all can give would be appreciated.  TIA.

- phil
Phil Sulak - 23 Jul 2004 04:58 GMT
Sorry, but I accidentally posted my message using the wrong "author
name".  No, I'm not trying to sell any of my Macs. Yes, I'm having a
problem with CW's delete[] operator and need help to stop my program
from leaking memory:-)

Thanks!

- phil
(philbert1@austin.rr.com; NOT macs4sale@austin.rr.com)
David Phillip Oster - 23 Jul 2004 07:27 GMT
> Hi All -
>
[quoted text clipped - 21 lines]
> int main()
> {
...
>    foo *foobar = new bar[1];
...
> }

Wow! if class bar is ever modified to contain any members, then:

class bar : public foo
{
  int mBar;
public:
  virtual ~bar() { cout << "bar dtor\n"; }
};

foo *foobar = new bar[2];

 fooBar[1] will reference into the middle of some object. (foobar is of
type foo*, but it is really pointing to an array of larger bars, so any
pointer arithmetic on foo will fail to align with the underlying
objects.)

If your program is really doing this, it sounds like a serious problem
that must be fixed immediately.

(Although, I do admit that the case of allocating an array length 1 (or
zero) is a special case that won't cause a problem.)
Phil Sulak - 23 Jul 2004 15:49 GMT
> foo *foobar = new bar[2];
>
>   fooBar[1] will reference into the middle of some object. (foobar is of
> type foo*, but it is really pointing to an array of larger bars, so any
> pointer arithmetic on foo will fail to align with the underlying
> objects.)

You're right, but luckily the code I'm working with doesn't have that
problem (phew!).  I think the original PC coders did casts as necessary
before doing any sort of pointer arithmetic.  If they hadn't, my code
would be crashing six ways from Sunday:-)

BTW, casting foobar to a (Bar *) before calling delete[] does fix my
leak problem.  But due to the huge number of subclasses I'm dealing
with, I unfortunately can't resort to doing that:-(

- phil
Matthew Collett - 23 Jul 2004 11:12 GMT
> I have a rather nasty problem regarding operator delete[] and CW 9.2.
> Calling delete[] on an object that was allocated with new[] but is then
> POINTED to by the object's superclass results in only 1 virtual dtor
> being called.

Don't Do That.  The C++ Standard says of delete[] that "if the dynamic
type of the object to be deleted differs from its static type, the
behavior is undefined" (5.3.4p3).  More accessibly, Item 3 of Meyers
"More Effective C++" explains why you should "Never treat arrays
polymorphically".

Best wishes,
Matthew Collett

Signature

Those who assert that the mathematical sciences have nothing to say
about the good or the beautiful are mistaken.          -- Aristotle

Howard Hinnant - 23 Jul 2004 15:52 GMT
> > I have a rather nasty problem regarding operator delete[] and CW 9.2.
> > Calling delete[] on an object that was allocated with new[] but is then
[quoted text clipped - 6 lines]
> "More Effective C++" explains why you should "Never treat arrays
> polymorphically".

<nod>  The easiest way to convert this into a conforming program on CW
9.2 (well, at least one of the easiest ways) is to:

  std::vector<std::tr1::shared_ptr<foo> > foobar(1,
std::tr1::shared_ptr<foo>(new bar));

-Howard
Phil Sulak - 23 Jul 2004 19:23 GMT
In article
<hinnant-B213F5.10523123072004@syrcnyrdrs-03-ge0.nyroc.rr.com>, Howard
Hinnant <hinnant@metrowerks.com> wrote:

> <nod>  The easiest way to convert this into a conforming program on CW
> 9.2 (well, at least one of the easiest ways) is to:
[quoted text clipped - 3 lines]
>
> -Howard

Very interesting -- thanks!  I may give this a try as an experiment,
but given the way the PC guys allocate objects in their original code
(via some rather nasty macros), this may not be the best solution for
me:-(

- phil
Phil Sulak - 23 Jul 2004 15:57 GMT
> Don't Do That.  The C++ Standard says of delete[] that "if the dynamic
> type of the object to be deleted differs from its static type, the
[quoted text clipped - 4 lines]
> Best wishes,
> Matthew Collett

Ahh, if only it were that easy:-)  Unfortunately, this problem is
althroughout the code and prevents me from easily re-engineering the
program.  I'm really hoping for a "nice" way to fix this problem (ie,
by using RTTI, a CW pragma, etc).  As I mentioned in my previous post,
casting foobar to a (bar *) does work, but unfortunately I can't easily
add casts to the code due to the numerous different subclassees that
need to be delete[]'d and the way they're managed in memory.

Differences between MSVC++ and CW are the WORST things to have to deal
with when porting code:-(

- phil
Miro Jurisic - 23 Jul 2004 19:07 GMT
> Differences between MSVC++ and CW are the WORST things to have to deal
> with when porting code:-(

Actually, the worst thing are incompetent windows programmers. The second worst
is the compiler.

The issue you raise here is a bug in their code and the right answer it to beat
them on the head with a stick until they fix it.

meeroh

Signature

If this message helped you, consider buying an item
from my wish list: <http://web.meeroh.org/wishlist>

Phil Sulak - 23 Jul 2004 19:19 GMT
> Actually, the worst thing are incompetent windows programmers. The second
> worst
[quoted text clipped - 5 lines]
>
> meeroh

LOL!

Thanks meeroh -- I needed a good laugh after dealing with this
problem:-)

- phil
Thorrsten Froehlich - 23 Jul 2004 20:49 GMT
> > Don't Do That.  The C++ Standard says of delete[] that "if the dynamic
> > type of the object to be deleted differs from its static type, the
[quoted text clipped - 15 lines]
> Differences between MSVC++ and CW are the WORST things to have to deal
> with when porting code:-(

You are missing the point here: The code is defective and needs
fixing. You are very lucky it does not (always) crash with VC. And the
programmer who wrote that code really needs to learn C++ programming
before he/she continues to do any more C++ hacking. Everything else is
a disaster waiting to happen.

   Thorsten
Wade Williams - 26 Jul 2004 19:05 GMT
> Differences between MSVC++ and CW are the WORST things to have to deal
> with when porting code:-(

In 99% of the cases I've found, CW is right.  Make the PC developers
change their code to meet the standard.

Wade
Wade Williams - 26 Jul 2004 19:07 GMT
> > Differences between MSVC++ and CW are the WORST things to have to deal
> > with when porting code:-(
>
> In 99% of the cases I've found, CW is right.  Make the PC developers
> change their code to meet the standard.

Whoops I just remembered where you work. :)

Never mind. :)

Wade
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.