crashing due to memory leaks Topic is solved

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
luker
Knows some wx things
Knows some wx things
Posts: 40
Joined: Wed Oct 25, 2006 10:23 am

crashing due to memory leaks

Post by luker » Fri Jan 19, 2007 12:05 pm

Hi Experts,

my program suffers from random crashes and I use a lot of wxString, wxString*, wxArrayString.
Do they behave like wxControls destroying themselves when their parents cease to exist?
Do I have to explicitly delete them after use?


Thanks in advance,

Lukas Schubert

phlox81
wxWorld Domination!
wxWorld Domination!
Posts: 1387
Joined: Thu Aug 18, 2005 7:49 pm
Location: Germany
Contact:

Post by phlox81 » Fri Jan 19, 2007 2:28 pm

Every new needs its delete.

In wxWidgets usually windows get destroyed by their parents.
So, you don't have to.
Doesn't go for a wxString*, depends also on where you create it, and how.
Try to run your program with the debugger, then you should get to the place
where it crashes.

luker
Knows some wx things
Knows some wx things
Posts: 40
Joined: Wed Oct 25, 2006 10:23 am

Post by luker » Fri Jan 19, 2007 3:43 pm

> Every new needs its delete.
I nearly guessed that.

> In wxWidgets usually windows get destroyed by their parents.
> So, you don't have to.
> Doesn't go for a wxString*, depends also on where you create it, and how.
most of the time it reads like

Code: Select all

wxString* strVariableName= new wxString( $initialisation$);
to create local variables.

> Try to run your program with the debugger, then you should get to the place where it crashes.
That is another problem. MinGW Developer Studio's Debug Build gets stuck in some error messages around wxAssert ( or wxAssert failure). Perhaps I should ask that in a seperate thread. But not in case you have the helping hint?


Ciao

Lukas Schubert

phlox81
wxWorld Domination!
wxWorld Domination!
Posts: 1387
Joined: Thu Aug 18, 2005 7:49 pm
Location: Germany
Contact:

Post by phlox81 » Fri Jan 19, 2007 4:34 pm

luker wrote:> Every new needs its delete.
I nearly guessed that.

> In wxWidgets usually windows get destroyed by their parents.
> So, you don't have to.
> Doesn't go for a wxString*, depends also on where you create it, and how.
most of the time it reads like

Code: Select all

wxString* strVariableName= new wxString( $initialisation$);
to create local variables.
what kind of "local" variables?
Those Variables need to be destroyed by you.
And for wxString, I think you can do without new.
luker wrote: > Try to run your program with the debugger, then you should get to the place where it crashes.
That is another problem. MinGW Developer Studio's Debug Build gets stuck in some error messages around wxAssert ( or wxAssert failure). Perhaps I should ask that in a seperate thread. But not in case you have the helping hint?
nope, debugging is not my strength.

luker
Knows some wx things
Knows some wx things
Posts: 40
Joined: Wed Oct 25, 2006 10:23 am

Post by luker » Sat Jan 20, 2007 9:45 am

what kind of "local" variables?
Do there exist several kinds?
If so, I supposedly use the most simple version:

Code: Select all

bool MyClass::MyMethod( int var1, float var2){
	wxString* strVar3= new wxString();
	strVar3->sprintf( "%d - %4.2f", var1, var2);
	wxMessageBox( strVar3->GetData());
	return( false);
}
does strVar3's occupied memory get freed by exiting the method?


Greetings

Lukas Schubert

Auria
Site Admin
Site Admin
Posts: 6695
Joined: Thu Sep 28, 2006 12:23 am
Contact:

Post by Auria » Sat Jan 20, 2007 3:23 pm

luker wrote: does strVar3's occupied memory get freed by exiting the method?
No, it's not freed. No variable created on the heap (i.e. with "new") is freed automatically. You would need to "delete strVar3" before leaving method, otherwise memory leaks. But even then this is not an elegant solution.

For a local variable, rather try:

Code: Select all

bool MyClass::MyMethod( int var1, float var2){
	wxString strVar3();
	strVar3.sprintf( "%d - %4.2f", var1, var2);
	wxMessageBox( strVar3.GetData() );
	return( false);
}
This one is freed automatically when leaving the method, because it's on the stack.

Giles
Knows some wx things
Knows some wx things
Posts: 31
Joined: Sat Jan 20, 2007 12:36 pm

Post by Giles » Sun Jan 21, 2007 8:39 am

Are you linking with DLL?
In this case I can explain why your program is crashing ( http://forums.wxwidgets.org/viewtopic.php?t=12187 )
Unfortunately I have no solution to this problem except using a static link.

If someone is using the DLL under MSW without crash due to allocation/deallocation problem I whould be happy to know how he does that!
Using Gcc of MinGW 5.1.2 + WxWidget 2.8.7 under XP

MichaelWard
Knows some wx things
Knows some wx things
Posts: 38
Joined: Thu Jul 13, 2006 9:36 pm

Post by MichaelWard » Tue Jan 23, 2007 3:27 pm

Giles:

I currently dynamically link my wxwidget programs to the wxWidget DLL as opposed to statically linking them. I also link my widgets programs to various other DLL's. Are you trying to link to the wxWidgets DLL that gives you all the classes, or did you create your own DLL with new classes etc derived from wxWidgets classes?

As for memory leaks is your going to write an umannaged C++ program which is what wxWidgets is, then you are going to have to learn a lot about the debugger and how to USE IT otherwise you will have endless problems and errors that people on forums will not really be able to help you with. Buy a simple Teach yourself C++ etc book and learn :)

Some Advice:
Add this to the header files of your projects for example, or if using pre-compiled header files then put this in that file.

Code: Select all

#ifdef _DEBUG
#include <crtdbg.h>
#define DEBUG_NEW new(_NORMAL_BLOCK ,__FILE__, __LINE__)
#else
#define DEBUG_NEW new
#endif
Then in every C++ .cpp file you create and write. Put the following near the top.

Code: Select all

#ifdef _DEBUG
#define new DEBUG_NEW
#endif
Now when you run your program in Debug Mode you will see what line of code is giving you memmory leaks. This should help you.

In my opinion though, I doubt your program is crashing due to memmory leaks. Nowadays, computers have so much memmory that it takes a lot of effort to use up all the memmory and cause the program to crash. (Assuming you are not actively trying to eat all the memmory). Your crash probably comes from pointers and accessing invalid memmory.

tan
Moderator
Moderator
Posts: 1471
Joined: Tue Nov 14, 2006 7:58 am
Location: Saint-Petersburg, Russia

Post by tan » Tue Jan 23, 2007 4:05 pm

Giles wrote:Are you linking with DLL?
In this case I can explain why your program is crashing ( http://forums.wxwidgets.org/viewtopic.php?t=12187 )
Unfortunately I have no solution to this problem except using a static link.

If someone is using the DLL under MSW without crash due to allocation/deallocation problem I whould be happy to know how he does that!
One possible issue is using different C-runtime libs (under Windows, for example, debug/release/dynamic/static) in app and DLLs and using actually bad practice to allocate memory in one place and to free it in another.
OS: Windows XP Pro
Compiler: MSVC++ 7.1
wxWidgets: 2.8.10

loptr
Earned some good credits
Earned some good credits
Posts: 110
Joined: Tue Jan 23, 2007 12:22 pm
Location: Kiel, Germany
Contact:

Post by loptr » Tue Jan 23, 2007 4:58 pm

i'm no expert in programming (so correct me if i'm wrong)...

but as far as i know, every object created with the new operator is created on the heap and thus needs manual deletion (at least it is highly recommended to delete them manually). and that's what you do when working with pointers to wxString objects like

Code: Select all

wxString* myString=new wxString();
so when you want to use local vars, try creating them on the stack as it will be deleted from the stack when leaving its area of validity, i.e. code block:

Code: Select all

void HeapStackFunction() {
    wxString* onTheHeap=new wxString(wxT("This string remains on the heap even when leaving the function"));

    wxString onTheStack=wxT("This string is automatically deleted on exit");

    if (1) {
        wxString againOnTheStack=wxT("This string is only valid inside the if block");
        
        wxString againOnTheHeap=new wxString(wxT("This string is also only valid within the if block"));
    }//if
   
    //ERROR: againOnTheStack is unknown at this point of code
    wxMessageBox(againOnTheStack.GetData()); 
    
    //ERROR: same as above, but this time you caused a 
    //       memory leak because access to againOnTheHeap is no longer possible. 
    //       BUT ONLY THE POINTER IS DELETED!!! 
    //       the object you created on the heap still exists...
    wxMessageBox(againOntheHeap.GetData()); 
}//HeapStackFunction
so don't forget to delete the heap objects!

as said above, please correct me if i'm wrong as this is a fundamental i'm counting on, and if i'm wrong there...

PS: yes, i know it's an old thread, but it has not yet been marked as resolved...

Giles
Knows some wx things
Knows some wx things
Posts: 31
Joined: Sat Jan 20, 2007 12:36 pm

Post by Giles » Tue Jan 23, 2007 9:09 pm

MichaelWard wrote:In my opinion though, I doubt your program is crashing due to memmory leaks. Nowadays, computers have so much memmory that it takes a lot of effort to use up all the memmory and cause the program to crash. (Assuming you are not actively trying to eat all the memmory). Your crash probably comes from pointers and accessing invalid memmory.
Michael, I completly agree with you. But taking your very sensible note as an basic hypothesis I have interpreted a fatal "memory leak" from the initial post as the most common memory management error which is freeing dangling pointers (pointers that are not pointing to an allocated memory block).
MichaelWard wrote:Are you trying to link to the wxWidgets DLL that gives you all the classes, or did you create your own DLL with new classes etc derived from wxWidgets classes?
I have tailored my wxWidget library by simply removing components of wxWidgets that I don't use (zip, Jpeg, png,...), by changing the setup.h file (no other files were harmed). I have faster compilation and linking by doing this. But I added nothing in the wxWidget library.

MichaelWard wrote:I currently dynamically link my wxwidget programs to the wxWidget DLL as opposed to statically linking them. I also link my widgets programs to various other DLL's.
I am very interested to know how you succeed to avoid allocating wxString in the DLL and freeing it your own code (I suppose you don't use the wxUSE_STL).
In fact when you allocate a string its constructor inlines a call to StringBase constructor:

Code: Select all

wxString(const wxChar *psz) : wxStringBase(psz ? psz : wxT("")) { }
Then the base constructor inlines a call to InitWith

Code: Select all

wxStringBase(const wxChar *psz){ InitWith(psz, 0, npos); }
which is finally a call to the corresponding DLL entry (the code of InitWith is not inlinable)
In this call the DLL entry allocates memory by calling malloc. This is the malloc that has been linked into the DLL. This malloc is managing its heap and provides a memory block inside this heap. All is perfect until now and you get a string buffer in a legal memory block.

But then you want to delete the string (I don't care if the string was allocated on the stack or the heap; that does not matter). This calls the implicit (no code) string destructor which is inlined in a StringBase destructor call that inlines a call to Unlock:

Code: Select all

~wxStringBase() { GetStringData()->Unlock(); }
void  Unlock() { if ( !IsEmpty() && --nRefs == 0) free(this);  }
This inlines in turn a call to free.

The pointer passed to free is actually the pointer that had been returned by the malloc so all seem perfect. BUT this time free is called in your code. You are not in the DLL this time. So you call the free linked in your EXE that is working on the heap of your EXE that is distinct of the heap of your DLL. So you try to return the memory block of a heap to another heap. Usually this does not crash. But if you are not lucky this does !

So I really don't know how to force the same level of inlining in contructor and destructor cases because you must always free the memory where you have allocated it. Practically I don't know how to enforce that. It is my question! How this works in your code? Did you check that your heaps (DLL and EXE) are not mixing in your application.

Note that the malloc / free pattern is the only case I know of procedures used in your code and in the DLL that refers to static variables. But there may be other cases of such duplication between the DLL and the EXE.

PS: when I replace the DLL by a static link (which I did when I gave up trying to force the right inlining) all my memory errors disappear (I know that this is not a proof with such kind of memory errors but I find this is an additional convincing clue that the DLL is responsible of the anomaly).

Sorry to have been so long but I felt a detailed explanation was necessary to understand such a subtle error.

-----------------------
tan wrote:One possible issue is using different C-runtime libs (under Windows, for example, debug/release/dynamic/static) in app and DLLs and using actually bad practice to allocate memory in one place and to free it in another.
As you can see above the problem is not to use 2 different libs but 2 different instances of the same lib (one linked in the DLL and one in the EXE)

-----------------------
loptr wrote:so don't forget to delete the heap objects!
as said above, please correct me if i'm wrong as this is a fundamental i'm counting on, and if i'm wrong there...
I did not check all in details but I think you are right. Though my current problem is not how we allocate/free the wxString but how wxString allocates/frees its internal buffer.
Using Gcc of MinGW 5.1.2 + WxWidget 2.8.7 under XP

Post Reply