-
Notifications
You must be signed in to change notification settings - Fork 256
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Tree & delete node (as button), 1.3.6, linux #251
Comments
Your program fails because it accesses deleted data. Try to run it with valgrind and you'll see... A much shorter test to see the effect goes like this (no need to click the button quickly):
Valgrind shows:
The first line shows that The reason why this happens is because the button is not deleted when the tree item is removed. It's invisible, but it's still there. Clicking on it again executes the callback which accesses the deleted tree item. Even your test accesses deleted data. It's disputable whether
Note that Your suggestion
wouldn't help because the tree item itself is deleted and accessing it after deletion would be forbidden anyway. You must make sure not to access deleted data in the first place. |
One more note: you may want to add |
Yeah, auto-deleting underlying widget when tree item is removed, seems expected/reasonable behavior by default for me. I'm a bit surprised, that it is not. (So, when the whole tree is deleted, the custom widgets in tree items still live... ??? ). Will try your solution, seems a bit better workaround...
Why so? OK, I understand that the button is not deleted, however I'd not expect, that it will receive clicks, when it's container (tree-item) is deleted/removed. |
When you create a custom button/custom widget to be used in Fl_Tree, it becomes a child of the Fl_Group which then 'owns' it. The widget's ownership is then managed with the inherited Fl_Group::xxx() methods (such as Fl_Group::clear(w), Fl_Group::remove(w), or Fl::delete_widget(w), etc) When you assign the widget to a particular Fl_Tree_Item with item->widget(your_widget), it's just associating the widget pointer to that particular item, not re-parenting it. (Fl_Tree_Item is not derived from Fl_Widget or Fl_Group). So the widget is still 'owned' by Fl_Group. This allows the widget to be unassigned from one Fl_Tree_Item (with item->remove(w)), and reassigned to another (with item->widget(w)), without needing to destroy + recreate the widget. To actually destroy the widget, first un-assign it from the item (using item->widget(0)) and then use the usual techniques to either remove or delete a child widget from an Fl_Group, e.g. Fl_Tree::Fl_Group::remove(w) to remove from the tree's group without deleting, or Fl::delete_widget(w) to remove + destroy, etc. |
Would it be possible together with assigning widget to TreeItem assign also ownership of it? (i.e. |
I didn't do this because in general its bad design to have two "owners" of an instance, and here Fl_Group really is the owner at all times; it has to be for events and such to operate properly. Also, arguably for consistency it would be necessary to provide Fl_Tree_Item::begin()/end()/add()/etc etc which takes things off the rails. If Fl_Tree_Item were itself an Fl_Group/Fl_Widget derived widget, then it would be OK, but Fl_Tree_Item is purposefully designed not to be for efficiency, so there can be hundreds or thousands of items without the overhead of an Fl_Group in each item, esp. when the items are not hosts of Fl_Widgets. I'd offer to solve the issues you're running into, the docs for Fl_Tree and Fl_Tree_Item::widget() should be fleshed out more about how to manage child widgets assigned to Fl_Tree_Items properly, esp. with regards to 'ownership' and the recommended way to delete/destroy. I'd also offer Fl_Group's docs should cover this too, as it's not clear from anything in Fl_Group how to properly destroy a child widget. Perhaps Fl_Group should have a virtual delete(w) (that simply calls Fl::delete_widget()) so it's easy to discern from the docs how to do this, and then by extension Fl_Tree could extend this method to ensure the widget is not only deleted from the group, but also un-assigns it from any tree item it's been associated with. I'd suggest opening a discussion on fltkcoredev to discuss API/doc improvements (so other devs can weigh in), as such conversations are pretty hidden within issues. |
FTR: deleting a widget and removing it from its parent ( There are some details in the docs of Fl::delete_widget() as well. The automatic removal from its parent group was obviously (as documented) introduced in 1.3.0. Side note: [1] with indirectly I mean deleting one of the parents of a widget which would recursively delete the widget itself, e.g. |
@basiliscos wrote:
When the whole Fl_Tree widget is deleted, this also deletes all child widgets. However, when a single Fl_Tree_Item is deleted, its associated widget (if any) is not deleted, as Greg explained. @erco77 I'm wondering if |
I used Fl_Browser for reference for the Fl_Tree API, as their needs are similar in terms of being a collection of items that are not derived from Fl_Widget. In the case of Fl_Tree::remove(), its docs read much like Fl_Browser::remove(), and neither elaborates on destruction but probably should, as both do destroy the item. Elaborating would prevent confusion with Fl_Group::remove(), which does /not/ destroy.
|
Ah, ok, I see. History and docs... ;) I don't want to go further into details, but anyway: Some time ago I thought I could make some |
Well, at very least the docs can be improved. I like showing examples in the widget class descriptions for doing things that are non-obvious or are common use patterns. An example added to Fl_Group's description showing how to properly delete a child widget in various contexts, both from normal methods and callbacks/event handlers could also be useful, as well as citing historical artifacts (like the changes in 1.3.0 that you mentioned), and techniques to avoid. |
I've opened a thread in fltkcoredev:
..so we can better hash this out, as one can't use text colors and such in issues, where I think it would be useful to explore doc changes. |
@erco77 Good move. We're gone way off-topic here and should move all further discussion to fltk.coredev @basiliscos I believe your issue is clear now and there's nothing we can do directly in FLTK for now. See also the discussion in fltk.coredev if you're interested. @basiliscos Can we close this issue? |
Yes, thanks a lot! |
Hi,
I have to following program:
When I add a few several nodes, and then quicly delete each one (by pressing on "del" button), I notice that callback is invoked twice for the same node which leads to segfault.
As a workaround, I have to checkk whether the current node can be found in it's parent, and only then delete it. This works, but I found it a bit clumpsy. I think it would be nice to add some internal "removed" flag into node itself, and when it is enablend then the call
tree->remove(node)
should just ignore the operation.What do you think?
The text was updated successfully, but these errors were encountered: