finalizing a GValue does not seem to call g_value_unset()
jcupitt opened this issue · comments
Hi, I think I've found a reference-counting problem and a clear explanation.
If some C code sets a GValue
to an object with g_value_set_object ()
, the value will hold a reference to the object, see:
Therefore when that GValue
is finalized, the reference must be dropped. This happens automatically when you call g_value_unset()
, see:
https://developer.gnome.org/gobject/stable/gobject-Generic-values.html#g-value-unset
This does not seem to happen, for example:
irb(main):001:0> require 'gir_ffi'
irb(main):002:0> GirFFI.setup :Vips
irb(main):003:0> Vips::init($PROGRAM_NAME)
irb(main):004:0> op = Vips::Operation.new "jpegload"
irb(main):005:0> op.set_property "filename", "/home/john/pics/k2.jpg"
irb(main):006:0> result = op.build
After setup, we have two objects: an operation and an image. The op we have built above, the image is held as a property of the op. The image has a single floating reference, and in turn holds a ref to the object.
You can see the counts with:
irb(main):007:0> Vips::Object::print_all
2 objects alive:
0) VipsForeignLoadJpegFile (0x24f5030), count=2
1) VipsImage (0x25a1010) 1080 bytes, count=1
Now we fetch the image property. The get_property
method on op will use g_value_set_object()
to set the GValue
to the image, adding another count:
irb(main):008:0> out = op.property("out")
=> #<GObject::Value:0x000000025c4570 @struct=#<GObject::Value::Struct:0x000000025c4548>>
irb(main):009:0> Vips::Object::print_all
2 objects alive:
0) VipsForeignLoadJpegFile (0x24f5030), count=2
1) VipsImage (0x25a1010) 1080 bytes, count=2
Now finalizing the GValue
should call g_value_unset()
and drop the ref, but it does not seem to do this:
irb(main):012:0> out = nil
irb(main):013:0> GC.start
irb(main):014:0> Vips::Object::print_all
2 objects alive:
0) VipsForeignLoadJpegFile (0x24f5030), count=2
1) VipsImage (0x25a1010) 1080 bytes, count=2
The counts are unchanged. I couldn't see a call to unset, though maybe I missed it:
john@bambam ~/GIT/gir_ffi (master) $ find . -name "*.rb" -exec grep -l unset {} \;
./test/integration/generated_regress_test.rb
This is with git master gir_ffi.
@jcupitt thanks for your detailed bug report. I'll look into it.
Fixed in master.