🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: borland.public.cppbuilder.nativeapi
Article #2499

Re: Memory Leak - TForm or TStringGrid or DynamicArray

#2499
From: Alan Bellingham
Date: Thu, 08 Feb 2007 15:37
112 lines
5237 bytes
Dan Mayo <do_not_spam_dmayo2@netzero.com> wrote:

>> Redundant test, BTW - delete NULL is safe anyway.
>
>What?
>
>TForm test;
>delete test;  //fails miserably

And so it should. That's not a pointer. That's illegal VCL, since you
can't declare a VCL object on the stack like that, and it won't compile.
And if it did, then it would be illegal C++, since C++ only allows
deleting pointers.

What is fine is

  TForm * test = NULL;
  delete test;

(BTW - not setting the pointer to null or some known valid value at the
point of declaration is asking for trouble. Pointers don't magically set
themselves to NULL. Trouble includes having strange things occurring.
What sort of strange things? Well, like what you're seeing.)

>Still don't understand why I am getting an exception when I try to 
>create a new TForm object.  The exception reports that I am out of 
>memory; however, if I immediately close the message saying the error 
>exists, and then try to create the form again all is well.

Who knows? Perhaps the code isn't getting as far as the assignment.
Perhaps you're leaking all over the place. It's difficult to know - the
code in question is fairly nasty looking.

What happens with the following? (I've wrapped the individual parts in
try/catch blocks purely for reporting purposes - in production code, I'd
take the try/catch blocks out entirely.)

  #include <memory> // for std::auto_ptr

  void Bar()
  {
    try {
      Application->ProcessMessages(); 
    } catch(...) {
      ShowMessage("Application->ProcessMessages() failed");
      throw;
    }

    try {
      std::auto_ptr<TSubForm> Foo(new TSubForm(this));
      try {
        //do some interesting things and update objects on Foo
        Foo->whatever();
      } catch (...) {
        ShowMessage("Some other error");
        throw;
      }
    } catch(...) {
      ShowMessage("Unable to create Foo");
      throw;
    }
  }

>Is there a way to test to see if I have enough memory, or pause until 
>there is enough memory, so that new TForm will succeed?

It's extremely unlikely that memory exhaustion is the problem. The usual
symptom of running out of memory is that your hard disk is thrashing
itself to death (and has been for ages), and Windows has ground to a
halt. Since you're not reporting this, I'm assuming that that's not
happening.

[ Caveat - (a) if you don't have virtual memory swap space set up, then
the disk thrash may not occur, and (b) if something within the TSubForm
constructor is trying to allocate huge amounts of memory (uninitialised
variable?), then you may have an insufficient memory state without
actually using it all up first. ]

What you see may be the result of a corrupted memory manager. In your
code, *IF* an exception occurs before you COMPLETE your 'new' statement,
then your finally block WILL cause massive, irreparable corruption of
your memory heap, due to the fact that the pointer will be some random
garbage non-NULL value. Anything that happens after that is in the lap
of the gods. You've got try/catch blocks everywhere, but you've not
managed to make your code safe.

(Compare with

  #include <memory> // for std::auto_ptr

  void Bar()
  {
    Application->ProcessMessages(); 
    std::auto_ptr<TSubForm> Foo(new TSubForm(this));
    //do some interesting things and update objects on Foo
    Foo->whatever();
  }

which *is* safe.)

I've said this before, and I'll say it again - if I see a delete in user
code, I consider it a warning sign that the code is probably unsafe. You
need to start using the RAII (Resource Allocation Is Initialisation)
idiom - it's incredibly powerful in making things safer *and* simpler,
and the part of C++ that I would miss most if I had to move to Java or
something else. Compare your code, with try/catch/finally all over the
place, with my three-liner.

Alan Bellingham
-- 
10th Anniversary ACCU Conference: 11-14 April 2007 - Oxford, UK
(Booking now open: see http://accu.org/index.php/conferences for details)
Technical Details
Message-ID: <ptems2p2k2rquqdiao805ik2fhg6jl9n9a@4ax.com>
Path: arc1-ca.pugleaf.net!g2news2.google.com!news3.google.com!news4.google.com!border1.nntp.dca.giganews.com!nntp.giganews.com!newsfeed00.sul.t-online.de!newsfeed01.sul.t-online.de!t-online.de!newsgroups.borland.com!not-for-mail
References: <45c7810f@newsgroups.borland.com> <45c7dc8d$1@newsgroups.borland.com> <45c89ec6@newsgroups.borland.com> <45ca4546$1@newsgroups.borland.com> <0sqks2t4c90epuc62bv635h36cqeat0ujd@4ax.com> <45cb3451$1@newsgroups.borland.com>

Show Full Headers
Complete Article Headers
X-Google-Thread: 10cc67,191a7d21d69bde32
X-Google-Attributes: gid10cc67,public
X-Google-Language: ENGLISH,ASCII-7-bit
From: Alan Bellingham <alan@lspace.org>
Newsgroups: borland.public.cppbuilder.nativeapi
Subject: Re: Memory Leak - TForm or TStringGrid or DynamicArray
Date: Thu, 08 Feb 2007 15:37:14 +0000
Organization: Private
Reply-To: alan@lspace.org
Message-ID: <ptems2p2k2rquqdiao805ik2fhg6jl9n9a@4ax.com>
References: <45c7810f@newsgroups.borland.com> <45c7dc8d$1@newsgroups.borland.com> <45c89ec6@newsgroups.borland.com> <45ca4546$1@newsgroups.borland.com> <0sqks2t4c90epuc62bv635h36cqeat0ujd@4ax.com> <45cb3451$1@newsgroups.borland.com>
X-Newsreader: Forte Agent 4.2/32.1117
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
NNTP-Posting-Host: 193.129.251.253
X-Trace: newsgroups.borland.com 1170949033 193.129.251.253 (8 Feb 2007 07:37:13 -0800)
Lines: 112
Path: arc1-ca.pugleaf.net!g2news2.google.com!news3.google.com!news4.google.com!border1.nntp.dca.giganews.com!nntp.giganews.com!newsfeed00.sul.t-online.de!newsfeed01.sul.t-online.de!t-online.de!newsgroups.borland.com!not-for-mail