Thread: [wxVTK] wxAuiNotebook with wxVTK
Brought to you by:
malat
From: KR L. <lo...@gm...> - 2008-04-07 20:56:25
|
Hello, I am using a wxAuiNotebook which has a page that is a wxVTKRenderWindowInteractor. Everything works fine until I either close the page or exit the application, at which time the application will crash or I get an error in the VTK debug window about trying to delete an object with a non-zero reference count, depending on how I handle deleting the wxVTKRenderWindowInteractor (wxVTK from here on). For simplicity, I'll focus on just the case of closing the application. If in the main frame's destructor, I do nothing to remove the wxVTK object, I get the error about deleting an object with a non-zero ref. count (makes sense). I added the wxVTKObject->Delete(), which does reduce the reference count to zero, but this causes a crash in wxObject (this is called from wxAuiNotebook::DeletePage()): bool wxObject::IsKindOf(wxClassInfo *info) const { wxClassInfo *thisInfo = GetClassInfo();// Crashes on this line return (thisInfo) ? thisInfo->IsKindOf(info) : false ; } I think I am successfully deleting the wxVTK object with the ->Delete() function, and then the notebook is trying to access it again in it's destructor. Is this something anyone has experienced before? Has anyone found a solution? I came up with a method that compiles and runs just fine, but I have doubts about whether or not this is a good (safe?) approach. I have not tested for memory leaks, but I suspect that if this method doesn't work, that will be why. Below is the code for my main frame's destructor: MainFrame::~MainFrame() { m_mgr.UnInit(); if (wxVTKObject) { wxVTKObject->Delete();// Delete the wxVTKRenderWindowInteractor the proper way wxWindow *Dummy = new wxWindow();// Create a dummy wxWindow // Assign the pointer for the wxVTKRenderWindowInteractor to point to a wxWindow // object instead. Now when the wxAuiNotebook is deleted, this will point to // something than can be deleted? wxVTKObject = (wxVTKRenderWindowInteractor*)Dummy; } } Is this OK? Is there a better way? I'm using wxWidgets 2.8.7 and VTK 5.0 in MSW. Thank you for your help, Kerry |
From: Sander N. <nie...@st...> - 2008-04-07 21:34:13
|
Dear Kerry, wxWidgets and VTK use different ways to delete objects. In this case you want to delete it yourself the VTK way which is using '...- >Delete()' and on the other hand a wx object is doing it the wxWidgets way and thinks it can call 'delete ...'. This generates a conflict. The delete will not decrese the VTK refcount and will result in your VTK error, but you can't really prevent the call to delete either (so doing your own Delete() will also give you trouble). I had this problem as well and got it solved differently: I was already using a derived class of wxVTKRenderWindowInteractor and for that class I added the following part to the destructor (at the end): ---- SetRenderWindow(NULL); SetInteractorStyle(NULL); // Normally one has to remove a wxVTKRenderWindowInteractor object using 'window->Delete()', // but we also would like 'delete window' to work (which is needed for e.g. Python wrapping) // This should be safe as long the reference count is 1 (i.e. no other objects have a reference to this object) // The problem is that we can't use Delete() or Unregister(NULL) here, because that would recursively invoke the // destructor. Therefore, we just explicitly decrease the reference count by 1 if it was 1 (this way you will still // get a warning from VTK if the reference count afterwards was not 0). if (GetReferenceCount() == 1) { SetReferenceCount(0); } --- This is the safest solution to this issue that I know of. Note that it also doesn't break a delete using the VTK-style Delete() mechanism (since it won't do anything special if the reference count is already 0, and the VTK Delete function will never call the destructor if the refcount was still higher than that). For your situation, you could probably adapt the wxVTKRenderWindowInteractor.cpp itself (instead of creating a subclass) and add the given routines to the (currently empty) wxVTKRenderWindowInteractor destructor. If this does indeed work, I think it might even be worth considering to add this reference count trick to the wxVTKRenderWindowInteractor destructor of the official wxVTKRenderWindowInteractor package. Mathieu? Best regards, Sander Niemeijer On 7 apr 2008, at 22:56, KR Loux wrote: > Hello, > > I am using a wxAuiNotebook which has a page that is a > wxVTKRenderWindowInteractor. Everything works fine until I either > close the page or exit the application, at which time the > application will crash or I get an error in the VTK debug window > about trying to delete an object with a non-zero reference count, > depending on how I handle deleting the wxVTKRenderWindowInteractor > (wxVTK from here on). For simplicity, I'll focus on just the case > of closing the application. If in the main frame's destructor, I do > nothing to remove the wxVTK object, I get the error about deleting > an object with a non-zero ref. count (makes sense). I added the > wxVTKObject->Delete(), which does reduce the reference count to > zero, but this causes a crash in wxObject (this is called from > wxAuiNotebook::DeletePage()): > > bool wxObject::IsKindOf(wxClassInfo *info) const > { > wxClassInfo *thisInfo = GetClassInfo();// Crashes on this line > return (thisInfo) ? thisInfo->IsKindOf(info) : false ; > } > > I think I am successfully deleting the wxVTK object with the - > >Delete() function, and then the notebook is trying to access it > again in it's destructor. Is this something anyone has experienced > before? Has anyone found a solution? > > I came up with a method that compiles and runs just fine, but I have > doubts about whether or not this is a good (safe?) approach. I have > not tested for memory leaks, but I suspect that if this method > doesn't work, that will be why. Below is the code for my main > frame's destructor: > > MainFrame::~MainFrame() > { > m_mgr.UnInit(); > > if (wxVTKObject) > { > wxVTKObject->Delete();// Delete the > wxVTKRenderWindowInteractor the proper way > wxWindow *Dummy = new wxWindow();// Create a dummy wxWindow > > // Assign the pointer for the wxVTKRenderWindowInteractor to > point to a wxWindow > // object instead. Now when the wxAuiNotebook is deleted, > this will point to > // something than can be deleted? > wxVTKObject = (wxVTKRenderWindowInteractor*)Dummy; > } > } > > Is this OK? Is there a better way? > > I'm using wxWidgets 2.8.7 and VTK 5.0 in MSW. > > > Thank you for your help, > > Kerry > ------------------------------------------------------------------------- > This SF.net email is sponsored by the 2008 JavaOne(SM) Conference > Register now and save $200. Hurry, offer ends at 11:59 p.m., > Monday, April 7! Use priority code J8TLD2. > http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone_______________________________________________ > Wxvtk-users mailing list > Wxv...@li... > https://lists.sourceforge.net/lists/listinfo/wxvtk-users |
From: Mathieu M. <mat...@gm...> - 2008-04-08 14:27:55
|
Hi there ! Long time no activity on wxVTK, glad to see it is still active :) Kerry, I made some minor tweaks to the wxVTK class so that the annoying debug leaks message does not appear anymore. You can now build VTK with DEBUG_LEAKS=ON safely. On Mon, Apr 7, 2008 at 11:33 PM, Sander Niemeijer <nie...@st...> wrote: > wxWidgets and VTK use different ways to delete objects. In this case > you want to delete it yourself the VTK way which is using '...- > >Delete()' and on the other hand a wx object is doing it the > wxWidgets way and thinks it can call 'delete ...'. This generates a > conflict. The delete will not decrese the VTK refcount and will result > in your VTK error, but you can't really prevent the call to delete > either (so doing your own Delete() will also give you trouble). > > I had this problem as well and got it solved differently: I was > already using a derived class of wxVTKRenderWindowInteractor and for > that class I added the following part to the destructor (at the end): > > ---- > SetRenderWindow(NULL); > SetInteractorStyle(NULL); That's always safe AFAIK. I can add those two lines to the destructor of wxVTK. > // Normally one has to remove a wxVTKRenderWindowInteractor > object using 'window->Delete()', > // but we also would like 'delete window' to work (which is > needed for e.g. Python wrapping) Yeah, that's where you got me lost. ->Delete() from VTK world always 'delete this', so whatever wxWindows wants should be included in the destructor (~wxVTK), but ->Delete is just a convention to call ~wxVTK() before doing some other VTK cleanups. > // This should be safe as long the reference count is 1 (i.e. no > other objects have a reference to this object) > // The problem is that we can't use Delete() or Unregister(NULL) > here, because that would recursively invoke the > // destructor. Therefore, we just explicitly decrease the > reference count by 1 if it was 1 (this way you will still > // get a warning from VTK if the reference count afterwards was > not 0). > if (GetReferenceCount() == 1) > { > SetReferenceCount(0); > } > --- > > This is the safest solution to this issue that I know of. > Note that it also doesn't break a delete using the VTK-style Delete() > mechanism (since it won't do anything special if the reference count > is already 0, and the VTK Delete function will never call the > destructor if the refcount was still higher than that). > > For your situation, you could probably adapt the > wxVTKRenderWindowInteractor.cpp itself (instead of creating a > subclass) and add the given routines to the (currently empty) > wxVTKRenderWindowInteractor destructor. > > If this does indeed work, I think it might even be worth considering > to add this reference count trick to the wxVTKRenderWindowInteractor > destructor of the official wxVTKRenderWindowInteractor package. Mathieu? I fixed the debug leaks thingy so that vtkDebugLeaks properly report whether or not every VTK classes has been deleted. AFAIK everything should be fine now (ie all vtkObject have a ref count == 0 at destruction time). I know that on Win32 there are some issues, which I thought were fixed in VTK 5.0, but this can be fixed as you mentionned by explicitely setting the Renderwindow to NULL before destruction. I'll add those two lines. And since I have some time on my hands, I'll review the couple of patch that were send to the mailing list, but from the top of my head they were already in CVS HEAD, simply not in wxVTK 1.2 Thanks everybody for continued support and suggestions, -- Mathieu |
From: Sander N. <nie...@st...> - 2008-04-09 08:32:50
|
Hi Mathieu, The problem is a matter of ownership. There are situations where you have to give ownership over who is responsible for deleting the wxVTK object to some other component (depending on the design of the framework you are using). In the situation I had it was because I use a Python wrapping for wxVTK. Because of the garbage collection that Python uses I can't call Delete() myself but have to rely on the fact that Python (through a SWIG wrapping) will call delete on the wxVTK object. My guess is that for the wxAuiNotebook the same reasoning holds. You can't call Delete() yourself, because the wxAuiNotebook has ownership of the destruction, so there is no single point where you can 'assist' in destroying the wxVTK object. In other words, you _should not_ call 'delete' or 'Delete()' yourself! So what does it mean if another component calls 'delete' on the wxVTK object? 1) It breaks the operation of all objects that still have a reference to the wxVTK object 2) It breaks the final decrement that a call of wxVTK::Delete() would do if there would be no further references (which raises a "Trying to delete object with non-zero reference count." error if the vtkObjectBase destructor gets called for the wxVTK object) So how do we remedy this? For the first problem we need to make sure that we have no more references to our object. For my purposes calling the SetRenderWindow(NULL) and SetInteractorStyle(NULL) from the wxVTK object destructor was sufficient. But depending on how you use the wxVTK object in your code you may have to remove additional references as well. For the second problem I use the 'if (GetReferenceCount() == 1) SetReferenceCount(0);' trick in the destructor. P.S. I saw that several of the items of the patch that I send in August last year are not in HEAD (yet). If you want to discuss them please drop me an email. Most importantly for me would be to drop the '#if (!wxCHECK_VERSION(2, 8, 0))' part. It may also be good to mention that wxWidgets 2.8 no longer supports GTK 1.2 (there are a lot of things broken). You will have to use GTK 2.x if you want to use wxWidgets 2.8.0. For our application we changed at some point from wxWidgets 2.6/GTK 1.2 to wxWidgets 2.8/GTK 2.x (we never got wxWidgets 2.6 properly working with GTK 2.x). Your mention in wxVTKRenderWindowInteractor.h of the flickering was I think exactly that issue. But this would then mean that: - wxWidgets 2.6 + GTK 1.2 -> use wxGLCanvas - wxWidgets 2.6 + GTK 2.0 -> don't use wxGLCanvas - wxWidgets 2.8 + GTK 1.2 -> will never work - wxWidgets 2.8 + GTK 2.0 -> don't use wxGLCanvas Best regards, Sander On 8 apr 2008, at 16:27, Mathieu Malaterre wrote: > Hi there ! > > Long time no activity on wxVTK, glad to see it is still active :) > > Kerry, I made some minor tweaks to the wxVTK class so that the > annoying debug leaks message does not appear anymore. You can now > build VTK with DEBUG_LEAKS=ON safely. > > On Mon, Apr 7, 2008 at 11:33 PM, Sander Niemeijer > <nie...@st...> wrote: >> wxWidgets and VTK use different ways to delete objects. In this case >> you want to delete it yourself the VTK way which is using '...- >>> Delete()' and on the other hand a wx object is doing it the >> wxWidgets way and thinks it can call 'delete ...'. This generates a >> conflict. The delete will not decrese the VTK refcount and will >> result >> in your VTK error, but you can't really prevent the call to delete >> either (so doing your own Delete() will also give you trouble). >> >> I had this problem as well and got it solved differently: I was >> already using a derived class of wxVTKRenderWindowInteractor and for >> that class I added the following part to the destructor (at the end): >> >> ---- >> SetRenderWindow(NULL); >> SetInteractorStyle(NULL); > > > That's always safe AFAIK. I can add those two lines to the > destructor of wxVTK. > >> // Normally one has to remove a wxVTKRenderWindowInteractor >> object using 'window->Delete()', >> // but we also would like 'delete window' to work (which is >> needed for e.g. Python wrapping) > > > Yeah, that's where you got me lost. ->Delete() from VTK world always > 'delete this', so whatever wxWindows wants should be included in the > destructor (~wxVTK), but ->Delete is just a convention to call > ~wxVTK() before doing some other VTK cleanups. > >> // This should be safe as long the reference count is 1 (i.e. no >> other objects have a reference to this object) >> // The problem is that we can't use Delete() or Unregister(NULL) >> here, because that would recursively invoke the >> // destructor. Therefore, we just explicitly decrease the >> reference count by 1 if it was 1 (this way you will still >> // get a warning from VTK if the reference count afterwards was >> not 0). >> if (GetReferenceCount() == 1) >> { >> SetReferenceCount(0); >> } >> --- >> >> This is the safest solution to this issue that I know of. >> Note that it also doesn't break a delete using the VTK-style Delete() >> mechanism (since it won't do anything special if the reference count >> is already 0, and the VTK Delete function will never call the >> destructor if the refcount was still higher than that). >> >> For your situation, you could probably adapt the >> wxVTKRenderWindowInteractor.cpp itself (instead of creating a >> subclass) and add the given routines to the (currently empty) >> wxVTKRenderWindowInteractor destructor. >> >> If this does indeed work, I think it might even be worth considering >> to add this reference count trick to the wxVTKRenderWindowInteractor >> destructor of the official wxVTKRenderWindowInteractor package. >> Mathieu? > > > I fixed the debug leaks thingy so that vtkDebugLeaks properly report > whether or not every VTK classes has been deleted. AFAIK everything > should be fine now (ie all vtkObject have a ref count == 0 at > destruction time). > I know that on Win32 there are some issues, which I thought were fixed > in VTK 5.0, but this can be fixed as you mentionned by explicitely > setting the Renderwindow to NULL before destruction. > > I'll add those two lines. And since I have some time on my hands, I'll > review the couple of patch that were send to the mailing list, but > from the top of my head they were already in CVS HEAD, simply not in > wxVTK 1.2 > > Thanks everybody for continued support and suggestions, > -- > Mathieu > > ------------------------------------------------------------------------- > This SF.net email is sponsored by the 2008 JavaOne(SM) Conference > Register now and save $200. Hurry, offer ends at 11:59 p.m., > Monday, April 7! Use priority code J8TLD2. > http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone > _______________________________________________ > Wxvtk-users mailing list > Wxv...@li... > https://lists.sourceforge.net/lists/listinfo/wxvtk-users |
From: Mathieu M. <mat...@gm...> - 2008-04-08 15:07:41
|
Hi Kerry, I never realized that wxWindows now has a ::Destroy, http://docs.wxwidgets.org/2.8.6/wx_wxwindow.html#wxwindow My guess is that VTK->Delete() & wxWidgets::Destroy() might now have conflicting behavior. What I do not understand is that no one before experienced the issue. Is this wx->Destroy() really that new ? The thing that I still do not understand is why don't you do something like that: wxVTKObject->Delete(); wxVTKObject = NULL; // tell wx not do manipulate this pointer anymore I have not looked at this wxAUI thingy... HTH -Mathieu On Mon, Apr 7, 2008 at 10:56 PM, KR Loux <lo...@gm...> wrote: > Hello, > > I am using a wxAuiNotebook which has a page that is a > wxVTKRenderWindowInteractor. Everything works fine until I either close the > page or exit the application, at which time the application will crash or I > get an error in the VTK debug window about trying to delete an object with a > non-zero reference count, depending on how I handle deleting the > wxVTKRenderWindowInteractor (wxVTK from here on). For simplicity, I'll > focus on just the case of closing the application. If in the main frame's > destructor, I do nothing to remove the wxVTK object, I get the error about > deleting an object with a non-zero ref. count (makes sense). I added the > wxVTKObject->Delete(), which does reduce the reference count to zero, but > this causes a crash in wxObject (this is called from > wxAuiNotebook::DeletePage()): > > bool wxObject::IsKindOf(wxClassInfo *info) const > { > wxClassInfo *thisInfo = GetClassInfo();// Crashes on this line > return (thisInfo) ? thisInfo->IsKindOf(info) : false ; > } > > I think I am successfully deleting the wxVTK object with the ->Delete() > function, and then the notebook is trying to access it again in it's > destructor. Is this something anyone has experienced before? Has anyone > found a solution? > > I came up with a method that compiles and runs just fine, but I have doubts > about whether or not this is a good (safe?) approach. I have not tested for > memory leaks, but I suspect that if this method doesn't work, that will be > why. Below is the code for my main frame's destructor: > > MainFrame::~MainFrame() > { > m_mgr.UnInit(); > > if (wxVTKObject) > { > wxVTKObject->Delete();// Delete the wxVTKRenderWindowInteractor the > proper way > wxWindow *Dummy = new wxWindow();// Create a dummy wxWindow > > // Assign the pointer for the wxVTKRenderWindowInteractor to point > to a wxWindow > // object instead. Now when the wxAuiNotebook is deleted, this will > point to > // something than can be deleted? > wxVTKObject = (wxVTKRenderWindowInteractor*)Dummy; > } > } > > Is this OK? Is there a better way? > > I'm using wxWidgets 2.8.7 and VTK 5.0 in MSW. > > > Thank you for your help, > > Kerry > > ------------------------------------------------------------------------- > This SF.net email is sponsored by the 2008 JavaOne(SM) Conference > Register now and save $200. Hurry, offer ends at 11:59 p.m., > Monday, April 7! Use priority code J8TLD2. > > http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone > _______________________________________________ > Wxvtk-users mailing list > Wxv...@li... > https://lists.sourceforge.net/lists/listinfo/wxvtk-users > > -- Mathieu |
From: Kerry L. <lo...@gm...> - 2008-04-08 15:54:18
|
Hello Mathieu, I am new to wxWidgets and have never used any version other than 2.8.7, so I can't say how new wx->Destroy() is. I did try to set the pointer to my wxVTKObject to NULL, but the app still crashes on exit. I don't think the problem is that wxWidgets wants to delete a NULL pointer (that's supposed to be safe?), it's that when the wxAuiNotebook::DeletePage() function is called (this gets called when the app closes as well as when a page closes), it tries to call member functions of the wxWindow that is on the notebook page. Looking through the code I get very confused - in wxAuiNotebook::DeletePage(), it makes this assignment: wxWindow* wnd = m_tabs.GetWindowFromIdx(page_idx); I would have guessed that this pointer is supposed to point to the page containing the wxVTKObject (which is now NULL), but then it calls wnd->IsKindOf() a few lines later. The crash occurs inside of IsKindOf() (when it tries to call wxObject::GetClassInfo()), not at the call for IsKindOf(). I can't explain why this is... In any case, I still prefer Sander's solution because it works for closing the application as well as closing just that one notebook tab. If I were to call wxVTK->Delete() and set the pointer to NULL, I'd have to put code in wxVTK's parent's destructor and I'd also have to catch notebook page close events, check to see if that page was a wxVTKObject, then do the special handling. Thanks for the responses! -Kerry On Tue, Apr 8, 2008 at 11:07 AM, Mathieu Malaterre < mat...@gm...> wrote: > Hi Kerry, > > I never realized that wxWindows now has a ::Destroy, > > http://docs.wxwidgets.org/2.8.6/wx_wxwindow.html#wxwindow > > My guess is that VTK->Delete() & wxWidgets::Destroy() might now have > conflicting behavior. What I do not understand is that no one before > experienced the issue. Is this wx->Destroy() really that new ? > > The thing that I still do not understand is why don't you do something > like that: > > wxVTKObject->Delete(); > wxVTKObject = NULL; // tell wx not do manipulate this pointer anymore > > I have not looked at this wxAUI thingy... > > HTH > -Mathieu > > On Mon, Apr 7, 2008 at 10:56 PM, KR Loux <lo...@gm...> wrote: > > Hello, > > > > I am using a wxAuiNotebook which has a page that is a > > wxVTKRenderWindowInteractor. Everything works fine until I either close > the > > page or exit the application, at which time the application will crash > or I > > get an error in the VTK debug window about trying to delete an object > with a > > non-zero reference count, depending on how I handle deleting the > > wxVTKRenderWindowInteractor (wxVTK from here on). For simplicity, I'll > > focus on just the case of closing the application. If in the main > frame's > > destructor, I do nothing to remove the wxVTK object, I get the error > about > > deleting an object with a non-zero ref. count (makes sense). I added > the > > wxVTKObject->Delete(), which does reduce the reference count to zero, > but > > this causes a crash in wxObject (this is called from > > wxAuiNotebook::DeletePage()): > > > > bool wxObject::IsKindOf(wxClassInfo *info) const > > { > > wxClassInfo *thisInfo = GetClassInfo();// Crashes on this line > > return (thisInfo) ? thisInfo->IsKindOf(info) : false ; > > } > > > > I think I am successfully deleting the wxVTK object with the ->Delete() > > function, and then the notebook is trying to access it again in it's > > destructor. Is this something anyone has experienced before? Has > anyone > > found a solution? > > > > I came up with a method that compiles and runs just fine, but I have > doubts > > about whether or not this is a good (safe?) approach. I have not tested > for > > memory leaks, but I suspect that if this method doesn't work, that will > be > > why. Below is the code for my main frame's destructor: > > > > MainFrame::~MainFrame() > > { > > m_mgr.UnInit(); > > > > if (wxVTKObject) > > { > > wxVTKObject->Delete();// Delete the wxVTKRenderWindowInteractor > the > > proper way > > wxWindow *Dummy = new wxWindow();// Create a dummy wxWindow > > > > // Assign the pointer for the wxVTKRenderWindowInteractor to > point > > to a wxWindow > > // object instead. Now when the wxAuiNotebook is deleted, this > will > > point to > > // something than can be deleted? > > wxVTKObject = (wxVTKRenderWindowInteractor*)Dummy; > > } > > } > > > > Is this OK? Is there a better way? > > > > I'm using wxWidgets 2.8.7 and VTK 5.0 in MSW. > > > > > > Thank you for your help, > > > > Kerry > > > > > ------------------------------------------------------------------------- > > This SF.net email is sponsored by the 2008 JavaOne(SM) Conference > > Register now and save $200. Hurry, offer ends at 11:59 p.m., > > Monday, April 7! Use priority code J8TLD2. > > > > > http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone > > _______________________________________________ > > Wxvtk-users mailing list > > Wxv...@li... > > https://lists.sourceforge.net/lists/listinfo/wxvtk-users > > > > > > > > -- > Mathieu > |