Open Ferada opened 6 years ago
Are you giving up on this, or is this somehow resolved? I am always suspect of hidden data on foreign side...
It's not solved no. At the moment I'm out of ideas of how to proceed here though.
The situation may be much worse than I thought.
So I am trying to figure out what happens to gtk-text-iters. As noted in this issue, @crategus mistakenly allocates new iters in every gtk-text-buffer and gtk-text-view function designed to mutate existinging iters. This results in thousands of iters generated while editing.
The function to free them, gtk-text-iter-free is not defined.
Is there some hidden dealocator? Iters are defined as boxed opaque types, and while I don't yet understand the implementation, it looks like define-g-boxed-opaque
macro has a provision for a finalizer for these. Inspecting the symbol gtk::gtk-text-iter
yields
NAME: @0=GTK-TEXT-ITER
TYPE: "GtkTextIter"
ALLOC: NIL
FREE: NIL
I tried to modify make-boxed-free-finalizer
to print something to see if it ever runs, but it does not appear to. It is possible that it is running in some thread that has no standard-output. So i created a counter, and added an incf to the function. Nope. 0. It is never called, apparently.
Edit: I also tried to see who calls gobject::g-boxed-type-register-static, which stores a user copy and deallocator functions... Apparently there are no callers. Also, no one seems to call g-boxed-free.
So as far as I can tell, iters are never deallocated.
A lot of this is historic code btw., coming from cl-gtk2
, not specifically how it was further developed in cl-cffi-gtk
, especially the way the iterators etc. have been introduced. Wrt. the other tickets, I agree that it's not ideal, yes.
That said, I'm pretty sure the deallocation happens via the finalizers (and then via g-idle-add
- you might simply not see that triggering in test code). Take a look at activate-gboxed-gc-hooks
and then enable the logs in gobject.init.lisp
, all the special variables at the top essentially, *debug-gc*
e.g.
I am not judging anyone for bad code... Just trying to figure it out (thanks for the pointers, I will try to track it down). In case of iters, I found that at the very least: 1) They are allocated by creating a blank foreign structure with 14 slots, calling the copy function, and deallocating the said structure; 2) They are allocated every time a buffer or view position function is called instead of using existing iters;
I am having trouble with debug logs as the logger calls print-object on gobject-class derived objects while they are being constructed, so a bunch of my print-object implementations crash trying to print slots that are not yet there... EDIT: actually, it crashes trying to print gtk-text-mark, so I don't know how to procede. EDIT: never mind, debugging. So it looks like iters are never deallocated, and nothing ever goes to gboxed-gc-hooks that I can catch.
E.g. a property of type
GVariantType
(which is basically an alias forchar*
) will fail to properly be translated onto the Lisp side. A bad fix (leaking memory) for this one particular case would be:Basically copying the boxed value, which would otherwise be unref-ed and therefore could point to invalid memory once examined on the Lisp side.
It seems like one more case of having to specify
:free-from-foreign
/:free-to-foreign
depending on the situation (if the boxed value is static there might be no need?). Alternatively the conversion could be done before the boxed value is being invalidated?