Thread View: borland.public.cppbuilder.nativeapi
30 messages
30 total messages
Started by Dan Mayo
Mon, 05 Feb 2007 19:10
Memory Leak - TForm or TStringGrid or DynamicArray
Author: Dan Mayo
Date: Mon, 05 Feb 2007 19:10
Date: Mon, 05 Feb 2007 19:10
23 lines
2077 bytes
2077 bytes
I have created some test code that dynamically creates a form; on that form is a button and a string grid. The button click event fills in a number of static objects with random data; then prior to exiting the function posts all that data into the StringGrid; this should in effect clean up those objects when the click even expires leaving just the data in the grid. That much works. However, when I close the form, when is then followed by a delete operator, the memory doesn't appear to be freed (looking at the Virtual Size of the program via the task manager). Reading the TStringGrid help, it looks as though I need to delete the 'objects' in the stringgrid too? How? Is there something else I am missing? I'm still trying to track down the problem I am having where I can't create a new TForm at random times that I posted in "Creating new TForm causes 'Out of Resources' error on WinXP" a few weeks ago. It's not that my program is taking up much memory, or the leak I see in the above test app is that big. I'm grasping at straws to find out what is going on here; any help would be appreciated. Thanks.
Re: Memory Leak - TForm or TStringGrid or DynamicArray
Author: Clayton Arends
Date: Mon, 05 Feb 2007 20:55
Date: Mon, 05 Feb 2007 20:55
29 lines
2027 bytes
2027 bytes
The data in the "Objects" property is not owned by the string grid. The
string grid makes no assumptions as to its contents. It is there solely for
the developer's needs.
To delete your objects you need to do something like the following.
// In the form's destructor
for (int col = 0, colCount = StringGrid1->ColCount;
col < colCount; ++col)
{
for (int row = 0, rowCount = StringGrid1->RowCount;
row < rowCount; ++row)
{
delete StringGrid1->Objects[col][row];
StringGrid1->Objects[col][row] = NULL; // optional
}
}
The above code assumes that the data stored in the objects array are truly
pointers to TObject descendants. If they are not then you will need to
reinterpret_cast to the appropriate type for delete to work correctly.
> The button click event fills in a number of static objects with random
> data
What do you mean by static objects? Can you show some code to explain what
you mean?
- Clayton
Re: Memory Leak - TForm or TStringGrid or DynamicArray
Author: Dan Mayo
Date: Mon, 05 Feb 2007 21:33
Date: Mon, 05 Feb 2007 21:33
130 lines
5374 bytes
5374 bytes
Dan Mayo wrote:
> I have created some test code that dynamically creates a form; on that
> form is a button and a string grid. The button click event fills in a
> number of static objects with random data; then prior to exiting the
> function posts all that data into the StringGrid; this should in effect
> clean up those objects when the click even expires leaving just the data
> in the grid. That much works.
>
> However, when I close the form, when is then followed by a delete
> operator, the memory doesn't appear to be freed (looking at the Virtual
> Size of the program via the task manager).
>
> Reading the TStringGrid help, it looks as though I need to delete the
> 'objects' in the stringgrid too? How? Is there something else I am
> missing?
>
> I'm still trying to track down the problem I am having where I can't
> create a new TForm at random times that I posted in "Creating new TForm
> causes 'Out of Resources' error on WinXP" a few weeks ago. It's not
> that my program is taking up much memory, or the leak I see in the above
> test app is that big. I'm grasping at straws to find out what is going
> on here; any help would be appreciated.
>
> Thanks.
>
>
The example code is as follows: (Note, MainForm, Form1's button1 event
contains a loop that dynamically creates a Form2 which is then deleted
after the modal operation is done; Form2 kicks off a timer when shown,
and the timer event does some processing, then returns a modal result;
Where is the memory leak? Of course the code operates faster when the
length of the dynamic array is defined before the first loop; the leak
is more pronounced (around 2k per pass) with the code as is; with the
length predefined, the leak appears to be around 2k per 10000 open and
closes.
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "MainForm.h"
#include "SubForm.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TForm2 *NewForm = new TForm2(this);
NewForm->ShowModal();
delete NewForm;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
for (int i=0; i<ScrollBar1->Position; i++)
{
Button1->Click();
StatusBar1->SimpleText = i;
Application->ProcessMessages();
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ScrollBar1Change(TObject *Sender)
{
Label1->Caption = ScrollBar1->Position;
}
//---------------------------------------------------------------------------
//SUBFORM
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "SubForm.h"
#include <math.h>
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm2 *Form2;
//---------------------------------------------------------------------------
__fastcall TForm2::TForm2(TComponent* Owner)
: TForm(Owner)
{
StringGrid1->ColCount = 0;
StringGrid1->RowCount = 0;
}
//---------------------------------------------------------------------------
void TForm2::DoTest()
{
StringGrid1->ColCount = 100;
StringGrid1->RowCount = 100;
DynamicArray<double> vs;
for (int i =0; i<100; i++)
{
for (int j=0; j<100; j++)
{
vs.Length++;
vs[i+j] = rand();
}
}
for (int i =0; i<100; i++)
{
for (int j=0; j<100; j++)
{
StringGrid1->Cells[i][j]=vs[i+j];
}
}
ModalResult = mrOk;
}
//---------------------------------------------------------------------------
void __fastcall TForm2::Timer1Timer(TObject *Sender)
{
Timer1->Enabled = false;
DoTest();
}
//---------------------------------------------------------------------------
Re: Memory Leak - TForm or TStringGrid or DynamicArray
Author: Remy Lebeau (TeamB)
Date: Tue, 06 Feb 2007 01:41
Date: Tue, 06 Feb 2007 01:41
18 lines
1661 bytes
1661 bytes
"Dan Mayo" <dmayo@dickey-john.com> wrote in message news:45c7810f@newsgroups.borland.com... > However, when I close the form, when is then followed by a delete > operator, the memory doesn't appear to be freed (looking at the > Virtual Size of the program via the task manager). You are not taking into account that the VCL uses its own memory manager that allocates larger amounts of memory from the OS and then buffers it out for its own allocations inside the application. Memory that is freed in code is not released back to the OS immediately. It is cached for later re-use. The Task Manager can only show memory that is allocated at the OS level, so you can't use it for tracking memory leaks in the VCL. That is what CodeGuard is for instead. Gambit
Re: Memory Leak - TForm or TStringGrid or DynamicArray
Author: Remy Lebeau (TeamB)
Date: Tue, 06 Feb 2007 01:49
Date: Tue, 06 Feb 2007 01:49
12 lines
1192 bytes
1192 bytes
"Dan Mayo" <dmayo@dickey-john.com> wrote in message news:45c7a28a@newsgroups.borland.com... > The example code is as follows <snip> > Where is the memory leak? There are no memory leaks in the code you have shown. Gambit
Re: Memory Leak - TForm or TStringGrid or DynamicArray
Author: Dan Mayo
Date: Tue, 06 Feb 2007 15:28
Date: Tue, 06 Feb 2007 15:28
23 lines
1765 bytes
1765 bytes
Remy Lebeau (TeamB) wrote:
> That is what CodeGuard is for instead.
I guess I will turn on CodeGuard and see what's going on; I've never
used it before.
Ok, so I run it, and I get an error immediately on startup that seems odd:
Method called on illegally casted object
Attempt to access 4 byte(s) at 0x006AC05C. The 'this' pointer
points to a block 0x006AC05C(....) which is only 1 bytes long
SETTINGS_FILE_NAME
And then points me to a problem in dstring.h
The SETTINGS_FILE_NAME is a constant string defined prior to my class
definition as:
String SETTINGS_FILE_NAME =
ExtractFileDir(Application->ExeName)+"\\settings.ini";
What's wrong with that?
Dan
Re: Memory Leak - TForm or TStringGrid or DynamicArray
Author: Dan Mayo
Date: Wed, 07 Feb 2007 21:30
Date: Wed, 07 Feb 2007 21:30
55 lines
2468 bytes
2468 bytes
Any ideas why I am still having an exception when I try to create a
TForm would be appreciated!
Dan Mayo wrote:
> Remy Lebeau (TeamB) wrote:
>> That is what CodeGuard is for instead.
Codeguard is now on. The only memory errors it reported were String
constructions such as the following:
const String SettingsFilePath =
ExtractFileDir(Application->ExeName)+"\\Settings.ini";
It reported attempting to index an out of bounds the char*; which to me
seemed odd; but I got rid of that error by using casting to the following:
const String SettingsFilePath =
ExtractFileDir(Application->ExeName)+static_cast<String>("\\Settings.ini");
Now, my code is running. No warnings or errors during compile or
PC-Lint, no errors reported by CodeGuard or EurekaLog during operation;
however, I am still getting an exception occasionally from the simplied
following:
void Bar()
{
TSubForm *Foo;
try
{
try
{
Application->ProcessMessages();
Foo = new TSubForm(this);
try
{
//do some interesting things and update objects on Foo
}
catch (...)
{
ShowMessage("Some other error occurred");
}
}
catch (...)
{
ShowMessage("Unable to create Foo");
}
}
__finally()
{
if (Foo!=NULL)
{
delete Foo;
}
}
}
Re: Memory Leak - TForm or TStringGrid or DynamicArray
Author: Alan Bellingham
Date: Thu, 08 Feb 2007 00:15
Date: Thu, 08 Feb 2007 00:15
14 lines
1428 bytes
1428 bytes
Dan Mayo <do_not_spam_dmayo2@netzero.com> wrote:
> if (Foo!=NULL)
> {
> delete Foo;
> }
Redundant test, BTW - delete NULL is safe anyway.
Alan Bellingham
--
Team Thai Kingdom
<url:http://www.borland.com/newsgroups/> Borland newsgroup descriptions
<url:http://www.borland.com/newsgroups/netiquette.html> netiquette
Re: Memory Leak - TForm or TStringGrid or DynamicArray
Author: Dan Mayo
Date: Thu, 08 Feb 2007 14:30
Date: Thu, 08 Feb 2007 14:30
14 lines
1636 bytes
1636 bytes
> Redundant test, BTW - delete NULL is safe anyway. What? TForm test; delete test; //fails miserably 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. 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?
Re: Memory Leak - TForm or TStringGrid or DynamicArray
Author: Alan Bellingham
Date: Thu, 08 Feb 2007 15:37
Date: Thu, 08 Feb 2007 15:37
112 lines
5237 bytes
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)
Re: Memory Leak - TForm or TStringGrid or DynamicArray
Author: Dan Mayo
Date: Thu, 08 Feb 2007 17:34
Date: Thu, 08 Feb 2007 17:34
5 lines
1289 bytes
1289 bytes
Alan Bellingham wrote: > std::auto_ptr<TSubForm> Foo(new TSubForm(this)); GREAT IDEA! I will try this.
Re: Memory Leak - TForm or TStringGrid or DynamicArray
Author: Remy Lebeau (TeamB)
Date: Thu, 08 Feb 2007 18:07
Date: Thu, 08 Feb 2007 18:07
19 lines
1727 bytes
1727 bytes
"Dan Mayo" <do_not_spam_dmayo2@netzero.com> wrote in message
news:45cb3451$1@newsgroups.borland.com...
> TForm test;
> delete test; //fails miserably
It is safe to call 'delete' on a NULL pointer. In the code above,
test is *not* NULL. It is not even a pointer, so you can't call
'delete' on it anyway. In case you meant to declare it as a pointer,
it would be an unintialized pointer, so it would have a random value.
Variables are not automatically intialized to zero when declared. You
have to do that explicitally in code, ie:
TForm *test = NULL;
delete test; // works fine
Gambit
Re: Memory Leak - TForm or TStringGrid or DynamicArray
Author: Dan Mayo
Date: Thu, 08 Feb 2007 22:51
Date: Thu, 08 Feb 2007 22:51
37 lines
2416 bytes
2416 bytes
Dan Mayo wrote:
> Alan Bellingham wrote:
> > std::auto_ptr<TSubForm> Foo(new TSubForm(this));
>
Ok, I have went thru all of my code and have changed to auto_ptrs for
the most part; and in places where I still need to use the pointer, I
have been sure to initialize it so that I don't attempt to delete a
pointer that hasn't been initialized.
The frequency of 'Out of Resources' messages has been reduced by this
change; but it still occurs, and it is in the same spot; except this
time rather that failing on a TSubForm *newform = new TSubForm(this);
it's failing on a std::auto_ptr<TSubForm> newform(TSubForm(this)); call.
Any additional ideas are greatly appreciated.
Thanks.
On a side note, is the following valid?
TSubForm *SubFormICanReferenceSomewhereElse = NULL;
void DoSomething()
{
if (SubFormICanReferenceSomewhereElse)
{
//do something with the SubFormICanReferenceSomewhereElse
}
}
void function()
{
std::auto_ptr<TSubForm> newform(TSubForm(this));
SubFormICanReferenceSomewhereElse = &*newform;
DoSomething();
SubFormICanReferenceSomewhereElse = NULL;
}
Re: Memory Leak - TForm or TStringGrid or DynamicArray
Author: Remy Lebeau (TeamB)
Date: Thu, 08 Feb 2007 23:49
Date: Thu, 08 Feb 2007 23:49
70 lines
3274 bytes
3274 bytes
"Dan Mayo" <do_not_spam_dmayo2@netzero.com> wrote in message
news:45cba995$1@newsgroups.borland.com...
> Ok, I have went thru all of my code and have changed to auto_ptrs
for
> the most part; and in places where I still need to use the pointer,
I
> have been sure to initialize it so that I don't attempt to delete a
> pointer that hasn't been initialized.
You shouldn't be deleting anything when using auto_ptr. That is the
whole point of auto_ptr - it frees the object for you automatically.
> std::auto_ptr<TSubForm> newform(TSubForm(this));
That is not a valid statement. You can't create VCL objects on the
stack. Perhaps you meant to call the 'new' operator instead?
std::auto_ptr<TSubForm> newform(new TSubForm(this));
> On a side note, is the following valid?
Yes (after you fix the above bug), though I would sggest you use the
auto_ptr's get() method instead:
void function()
{
std::auto_ptr<TSubForm> form(new TSubForm(NULL));
SubFormICanReferenceSomewhereElse = form.get(); // <--
DoSomething();
SubFormICanReferenceSomewhereElse = NULL;
}
Of course, if DoSomething() throws an exception, then
SubFormICanReferenceSomewhereElse will not be reset to NULL, though
the TForm will have been freed. You would need an exception handler
to ensure it gets reset correctly:
void function()
{
std::auto_ptr<TSubForm> form(new TSubForm(this));
SubFormICanReferenceSomewhereElse = form.get();
try
{
DoSomething();
}
catch(...)
{
}
SubFormICanReferenceSomewhereElse = NULL;
}
It would be better to pass the TForm pointer as a parameter instead of
using a global:
void DoSomething(TSubForm *Form)
{
if( Form )
// do something with the Form
}
void function()
{
std::auto_ptr<TSubForm> form(new TSubForm(NULL));
DoSomething(form.get());
}
Gambit
Re: Memory Leak - TForm or TStringGrid or DynamicArray
Author: Ed Mulroy
Date: Fri, 09 Feb 2007 00:56
Date: Fri, 09 Feb 2007 00:56
13 lines
1626 bytes
1626 bytes
> ...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...
std::auto_ptr<char> Foo(new char[26]);
As the old saying goes, "all full generalizations are wrong, including this
one" <g>
. Ed
> Alan Bellingham wrote in message
> news:ptems2p2k2rquqdiao805ik2fhg6jl9n9a@4ax.com...
Re: Memory Leak - TForm or TStringGrid or DynamicArray
Author: Alan Bellingham
Date: Fri, 09 Feb 2007 08:41
Date: Fri, 09 Feb 2007 08:41
20 lines
1860 bytes
1860 bytes
"Ed Mulroy" <dont_email_me@bitbuc.ket> wrote: >> ...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... > > std::auto_ptr<char> Foo(new char[26]); > >As the old saying goes, "all full generalizations are wrong, including this >one" <g> Well, I didn't add the 'new considered unsafe' too, did I *grin* That one is best replaced by std::vector<char> Foo(26). Alan Bellingham -- Team Thai Kingdom <url:http://www.borland.com/newsgroups/> Borland newsgroup descriptions <url:http://www.borland.com/newsgroups/netiquette.html> netiquette
Re: Memory Leak - TForm or TStringGrid or DynamicArray
Author: Dan Mayo
Date: Fri, 09 Feb 2007 15:03
Date: Fri, 09 Feb 2007 15:03
17 lines
2043 bytes
2043 bytes
> That is not a valid statement. You can't create VCL objects on the
> stack. Perhaps you meant to call the 'new' operator instead?
>
> std::auto_ptr<TSubForm> newform(new TSubForm(this));
Yes, that's exactly what I have in the code; I just fat fingered the
post and left off the 'new'.
The code again crashed sometime last night. EurekaLog points to where
the crash occurred on the following line:
std::auto_ptr<TSubForm> form(new TSubForm(NULL));
Oh why is it still crashing?
I'm going to modify the code now so that I don't dynamically create the
form in question, but instead have one static form for that one
function. Perhaps that will help point to where the real problem is?
Re: Memory Leak - TForm or TStringGrid or DynamicArray
Author: Dan Mayo
Date: Fri, 09 Feb 2007 15:16
Date: Fri, 09 Feb 2007 15:16
15 lines
1966 bytes
1966 bytes
> I'm going to modify the code now so that I don't dynamically create the
> form in question, but instead have one static form for that one
> function. Perhaps that will help point to where the real problem is?
Well, the following doesn't work, in so much that when the program
exists I get a access violation error when subform attempted to be
cleaned up:
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
static std::auto_ptr<TForm> subform(new TForm(this));
subform->ShowModal();
}
//---------------------------------------------------------------------------
Re: Memory Leak - TForm or TStringGrid or DynamicArray
Author: Alan Bellingham
Date: Fri, 09 Feb 2007 15:16
Date: Fri, 09 Feb 2007 15:16
14 lines
1938 bytes
1938 bytes
Dan Mayo <do_not_spam_dmayo2@netzero.com> wrote: >I'm going to modify the code now so that I don't dynamically create the >form in question, but instead have one static form for that one >function. Perhaps that will help point to where the real problem is? It might help the problem go away. Creating and destroying the same form again and again may be less efficient than creating it once, and then hiding or showing it as required. Alan Bellingham -- 10th Anniversary ACCU Conference: 11-14 April 2007 - Oxford, UK (Booking now open: see http://accu.org/index.php/conferences for details)
Re: Memory Leak - TForm or TStringGrid or DynamicArray
Author: Alan Bellingham
Date: Fri, 09 Feb 2007 15:35
Date: Fri, 09 Feb 2007 15:35
29 lines
2350 bytes
2350 bytes
Dan Mayo <do_not_spam_dmayo2@netzero.com> wrote:
>Well, the following doesn't work, in so much that when the program
>exists I get a access violation error when subform attempted to be
>cleaned up:
>
>//---------------------------------------------------------------------------
>void __fastcall TForm1::Button1Click(TObject *Sender)
>{
>static std::auto_ptr<TForm> subform(new TForm(this));
>subform->ShowModal();
>}
I'd be very tempted to let it leak. Yes, leaking is usually bad news,
but a once-per-program leak is (assuming no weird transactions are
expected during cleanup) not normally a problem. Except that CodeGuard
will moan. So:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
static TForm* subform(new TForm(this));
}
End of lifetime with forms can be a problem.
Alan Bellingham
--
10th Anniversary ACCU Conference: 11-14 April 2007 - Oxford, UK
(Booking now open: see http://accu.org/index.php/conferences for details)
Re: Memory Leak - TForm or TStringGrid or DynamicArray
Author: Dan Mayo
Date: Fri, 09 Feb 2007 16:23
Date: Fri, 09 Feb 2007 16:23
19 lines
2109 bytes
2109 bytes
> I'd be very tempted to let it leak. Yes, leaking is usually bad news,
> but a once-per-program leak is (assuming no weird transactions are
> expected during cleanup) not normally a problem. Except that CodeGuard
> will moan. So:
>
> void __fastcall TForm1::Button1Click(TObject *Sender)
> {
> static TForm* subform(new TForm(this));
> }
>
> End of lifetime with forms can be a problem.
>
So the exception reported when the static case of a form above is used
is a fact-of-life?
BTW, in this case, CodeGuard doesn't moan; the program reports an
exception error and the pc politely asks me if I would like to email
bill gates with the details.
Re: Memory Leak - TForm or TStringGrid or DynamicArray
Author: Ed Mulroy
Date: Fri, 09 Feb 2007 16:40
Date: Fri, 09 Feb 2007 16:40
36 lines
2622 bytes
2622 bytes
> That one is best replaced by std::vector<char> Foo(26). IFF vector<char> can easily do what is needed. Both new/new[] and delete/delete[] have their uses. The uses just are not nearly as common as a new programmer might think (interesting thought - how about a new term "new programmer" as a pun in that the new programmer frequently programs with "new"). FWIW: In normal programs I use new/new[] and delete/delete[] frequently but they are almost exclusively found in constructors and destructors. In small (one-source-file main/WinMain and but a few functions 'quicky' programs) I usually don't use RAII at all and both new/new[] and delete/delete[] are used with impunity. In those cases things are so simple that there is little chance of missing a delete/delete[] by mistake or by exception. . Ed > Alan Bellingham wrote in message > news:0scos2d8fs92eis2eo0a7j91shnaaedbrd@4ax.com... > >>> ...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... >> >> std::auto_ptr<char> Foo(new char[26]); >> >>As the old saying goes, "all full generalizations are wrong, >>including this one" <g> > > Well, I didn't add the 'new considered unsafe' too, did I *grin* > > That one is best replaced by std::vector<char> Foo(26).
Re: Memory Leak - TForm or TStringGrid or DynamicArray
Author: Clayton Arends
Date: Fri, 09 Feb 2007 17:21
Date: Fri, 09 Feb 2007 17:21
6 lines
1813 bytes
1813 bytes
static variables are cleaned up far after the VCL has cleaned up behind itself. Since you specified that the form is owned by TForm1 it will destroy your subform when it gets deleted itself. What you are seeing is a double deletion. In this case don't use the auto_ptr and there is no leak. - Clayton
Re: Memory Leak - TForm or TStringGrid or DynamicArray
Author: Alan Bellingham
Date: Fri, 09 Feb 2007 17:27
Date: Fri, 09 Feb 2007 17:27
24 lines
2376 bytes
2376 bytes
"Ed Mulroy" <dont_email_me@bitbuc.ket> wrote: >that there is little chance of Ah, that wonderful phrase: 'little chance'. I was rung up by my manager this morning. A program had stopped working at a client site, because a year ago, I appear to have typed '8' rather than '28', and as a result, an expiry cut in 20 days early. (We were going to provide the free updated version next week, in plenty of time for the end of this month.) Little chance that I'd have done that. Little chance that the mistake would have been missed by testing. Yet, the bug was there on the customer site, and was here when I checked the relevant executable too. (Said code was a 'temporary hack', a couple of years ago, initially to last for a month. Little chance it'd be required for much longer than that. *cough*) Alan Bellingham -- 10th Anniversary ACCU Conference: 11-14 April 2007 - Oxford, UK (Booking now open: see http://accu.org/index.php/conferences for details)
Re: Memory Leak - TForm or TStringGrid or DynamicArray
Author: Remy Lebeau (TeamB)
Date: Fri, 09 Feb 2007 19:02
Date: Fri, 09 Feb 2007 19:02
32 lines
2304 bytes
2304 bytes
"Dan Mayo" <do_not_spam_dmayo2@netzero.com> wrote in message
news:45cc8d73$1@newsgroups.borland.com...
> The code again crashed sometime last night. EurekaLog points to
> where the crash occurred on the following line:
> std::auto_ptr<TSubForm> form(new TSubForm(NULL));
There is no way that auto_ptr can crash. The crash has to be occuring
inside your TForm itself during its construction, probably during the
DFM streaming. One of the controls is likely doing something it
shouldn't be doing.
> Oh why is it still crashing?
One thing I just noticed in your earlier message is the following:
__fastcall TForm2::TForm2(TComponent* Owner)
: TForm(Owner)
{
StringGrid1->ColCount = 0;
StringGrid1->RowCount = 0;
}
You can't set the RowCount to zero. TStringGrid requires at least 1
non-fixed row at all times. Why Borland designed TStringGrid that
way, I have no clue.
Are you still using that code in your TSubForm?
Gambit
Re: Memory Leak - TForm or TStringGrid or DynamicArray
Author: Remy Lebeau (TeamB)
Date: Fri, 09 Feb 2007 19:02
Date: Fri, 09 Feb 2007 19:02
13 lines
1760 bytes
1760 bytes
"Dan Mayo" <do_not_spam_dmayo2@netzero.com> wrote in message news:45cc9095$1@newsgroups.borland.com... > Well, the following doesn't work, in so much that when the program > exists I get a access violation error when subform attempted to be > cleaned up: Then you are obviously doing something wrong inside the TForm itself. What does it actually do? What does its code look like? Gambit
Re: Memory Leak - TForm or TStringGrid or DynamicArray
Author: Remy Lebeau (TeamB)
Date: Fri, 09 Feb 2007 19:05
Date: Fri, 09 Feb 2007 19:05
19 lines
1993 bytes
1993 bytes
"Dan Mayo" <do_not_spam_dmayo2@netzero.com> wrote in message
news:45cc9095$1@newsgroups.borland.com...
> void __fastcall TForm1::Button1Click(TObject *Sender)
> {
> static std::auto_ptr<TForm> subform(new TForm(this));
> subform->ShowModal();
> }
That is very dangerous code. Because the auto_ptr is static, it will
not be freed when the methods exits, but when the program is shut down
instead. However, you have also assigned an Owner to the TForm as
well. So that means that you have two different objects owning the
same TForm instance. So you are going to end up with the TForm being
destroyed twice at two different times.
Gambit
Re: Memory Leak - TForm or TStringGrid or DynamicArray
Author: Ed Mulroy
Date: Fri, 09 Feb 2007 19:23
Date: Fri, 09 Feb 2007 19:23
26 lines
2530 bytes
2530 bytes
FYI: When I said "little chance" it was about small programs such as a little utility I write to convert one file to another format, never to be used again. It was never meant to refer to anything which would get into production code, even as a temporary hack. . Ed > Alan Bellingham wrote in message > news:c9bps2hh072ogocfl3qhea00rf05tj5gpa@4ax.com... > > Ah, that wonderful phrase: 'little chance'. > > I was rung up by my manager this morning. A program had stopped working > at a client site, because a year ago, I appear to have typed '8' rather > than '28', and as a result, an expiry cut in 20 days early. (We were > going to provide the free updated version next week, in plenty of time > for the end of this month.) > > Little chance that I'd have done that. Little chance that the mistake > would have been missed by testing. Yet, the bug was there on the > customer site, and was here when I checked the relevant executable too. > > (Said code was a 'temporary hack', a couple of years ago, initially to > last for a month. Little chance it'd be required for much longer than > that. *cough*)
Re: Memory Leak - TForm or TStringGrid or DynamicArray
Author: Dan Mayo
Date: Fri, 09 Feb 2007 20:01
Date: Fri, 09 Feb 2007 20:01
44 lines
3096 bytes
3096 bytes
Remy Lebeau (TeamB) wrote:
> There is no way that auto_ptr can crash.
Oh but it did, I'd send you the EurekaLog if it would prove anything or
satisfy anything.
> Are you still using that code in your TSubForm?
No. The subform has really nothing on it. Here is all the code on the
subform, with the names changed to protect the innocent:
//---------------------------------------------------------------------------
__fastcall TSubForm::TSubForm(TComponent* Owner)
: TForm(Owner)
{
Stopped = false; //private bool
//note there are two other components on the form, a TProgressBar and
a TLabel.
}
//---------------------------------------------------------------------------
void __fastcall TSubForm::StopProcessButtonClick(TObject *Sender)
{
StopButton->Visible = false; //TButton
Stopped = true;
}
//---------------------------------------------------------------------------
void __fastcall TSubForm::FormShow(TObject *Sender)
{
StopButton->Visible = true;
Stopped = false;
}
//---------------------------------------------------------------------------
On a lighter note, I got rid of the static std::auto_ptr, and changed
the function call so that instead of dynamically creating the subform
during that function, I now create the subform only once in the main
forms constructor and then the function simply shows and hides it. I
didn't want to do it that way, but as I said this is a lighter note; and
the code is working. No Lint errors, no Eureka Log errors yet; and no
CodeGuard errors.
So in any event, like it or not I think I have the problem resolved by
simply deciding to no longer dynamically create the subform. Now to
better things.
Re: Memory Leak - TForm or TStringGrid or DynamicArray
Author: Remy Lebeau (TeamB)
Date: Fri, 09 Feb 2007 21:13
Date: Fri, 09 Feb 2007 21:13
20 lines
2005 bytes
2005 bytes
"Dan Mayo" <do_not_spam_dmayo2@netzero.com> wrote in message news:45ccd362$1@newsgroups.borland.com... > Oh but it did That was not a crash in auto_ptr itself. That was a crash in the construction of the TForm *before* the auto_ptr was created. > No. The subform has really nothing on it. Here is all the code on the > subform, with the names changed to protect the innocent: There is nothing in that code that can cause the kind of crashing you are describing. So that leave another possibility - code elsewhere in your project is probably messing up memory, causing random crashes in unrelated areas. Gambit
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