[Solved] How can I free() the real children?
BlitzMax Forums/BlitzMax Beginners Area/[Solved] How can I free() the real children?
| ||
Local ii:wxWindow[] = MOBii_Panel[q].Panel.getChildren() If ii Then For Local i:wxWindow = EachIn ii If i.getID() Then i.Free() Next End IfHow can I free() the real children? |
| ||
Hi, are you trying to free a wxWidget window ? Do you want to free parent and it's children or just the children ? -Henri |
| ||
MOBii_Panel[q].Panel = New wxScrolledWindow.Create(wxWindow(po), b, _x, _y, _w, _h, wxHSCROLL|wxVSCROLL|$00080000)panel is a wxScrolledWindow Example of children: wxListBox, wxSlider, wxButton, wxCheckBox, wxStaticText my test show me that when I i.Free() I only Free() the local i copy Local ii:wxWindow[] = MOBii_Panel[q].Panel.getChildren() If ii Then For Local i:wxWindow = EachIn ii If i.getID() Then i.Free() echo "This is the real child: " + MOBii_Button[0].getID() ' and it print out the id, so it mean the real object is still alive! Next End If if I don't know: MOBii_Button[0].Free() how can I free the original object? I know: MOBii_Panel[q].Panel.getChildren() |
| ||
From wxWiki: Avoiding Memory Leaks The wxWidgets-specific part If we're talking about a class that is derived off wxWindow, there are some special issues: a wxWindow may get events, and if there's an event that should go to an object that has since been deleted, that may make your program crash. This is why a wxWindow (or wxWindow-derived class) should be deleted with care, first making sure there are no pending events bound for that object. This is done with the Destroy()-method of wxWindow. Instead of using delete, you must use myWindow->Destroy(), which will wait until next idle loop and then do something like delete myWindow;. For the same reason, you may never create a wxWindow-derived class on the stack (!), since that will be deleted automatically without using Destroy(). Thus for wxWindow-derived classes, you must always use new and ->Destroy(). There is however one exception to this, see #Modal windows below. Child windows When a wxWindow is destroyed, it automatically deletes all its children. These children are all the objects that received the window as the parent-argument in their constructors. As a consequence, if you're creating a derived class that contains child windows, you should use a pointer to the child windows instead of the objects themself as members of the main window. That is, do class myNotebook: public wxNotebook { private: wxPanel * panel1; wxPanel * panel2; } instead of class myNotebook: public wxNotebook { private: wxPanel panel1; wxPanel panel2; } The second format would cause double-deletion problems. "Managed" windows For "managed" windows, like frames and dialogs, it is usually better to call ->Close() instead of ->Destroy(). This will generate an EVT_CLOSE before destroying the object. If for some reason you want to delete a control yourself, you would use ->Destroy(), since controls are non-managed windows and do not respond to the EVT_CLOSE;. Note: When calling ->Close(), memory is not actually freed, but the dialog is just hidden from the user. If you really want to free the memory, you will need to call ->Destroy(). If the dialog has been given a parent frame, you may just call ->Close() as the dialog will be destroyed and freed when the parent frame is. According to this you should use Destroy() for freeing control from memory also. This should free every child as well, and there might be a slight delay also before every event is processed in order to free properly. Just for fun here is my function to go through every child control for any given parent. I use it to clear a form: 'Clear all child controls Function ClearFields(parent:Object) Local win:wxWindow = wxWindow(parent) If Not win Then Return Local kids:wxWindow[] = win.GetChildren() For Local kid:wxWindow = EachIn kids If kid.GetChildren() Then ClearFields(kid) 'Type Casting is used to distinguish different controls for control spesific actions Local tmpField:wxTextCtrl = wxTextCtrl(kid) If tmpField Then tmpField.SetValue("") EndIf Local tmpCombo:wxComboBox = wxComboBox(kid) If tmpCombo Then 'tmpCombo.SelectItem(0) tmpCombo.Clear() tmpCombo.SetValue("") EndIf Local tmpChoice:wxChoice = wxChoice(kid) If tmpChoice Then tmpChoice.SelectItem(0) EndIf Next EndFunction -Henri |
| ||
WOW I made it, thanks again Henri I kill the panel: If Panel.wxObjectPtr Then Panel.hide(); KilltheChildren(Panel); Panel.Free() ' I can still only: Panel.Free() not Panel.Destroy(), Maybe that is the reason I can't kid.Destroy() the panel in the KilltheChildrenModified Henri code ' -----------------------------------------------------------------------[KilltheChildren]--- Method KilltheChildren(_father:Object) Local win:wxWindow = wxWindow(_father) If Not _father Then Return Local kids:wxWindow[] = win.getChildren() If kids Then For Local kid:wxWindow = EachIn kids If kid.wxObjectPtr Then If kid.getChildren() Then KilltheChildren(kid) If kid.wxObjectPtr Then kid.hide() Local _k:wxScrolledWindow = wxScrolledWindow(kid) If Not _k Then DebugLog "NOT a panel :: kill subkid: " + kid.getID(); kid.Destroy() End If End If Next End If End Methodif I don't kill the sub panels in the KilltheChildren() I don't get the EXCEPTION_ACCESS_VIOLATION crash and the script leak less memory now ^^/ Footnote: I make a memory test to draw 100 wxStaticText and the editor start crying I almost start crying to until I realize that drawing 100 wxStaticText make the application really slow! |