Subject:
[ruby-ffi] AutoPointer#free incorrect?
From:
cfis
Date:
8/30/11 2:24 AM
To:
ruby-ffi

Unless I'm missing something, it looks to me that the implementation
of #free is not correct.  I am wrapping FreeImage and have code like
this:

class Bitmap
    def self.release(ptr) #:nodoc:
      FreeImage.FreeImage_Unload(ptr)
    end
end

Now I load an image:

 bitmap = load_some_bitmap

In time it will get GC'ed, but let's say I want to force the issue:

  bitmap.free

That calls AutoPointer#free

    def free
      @releaser.free
    end

Which in turn calls Releaser#free:

      def free
        raise RuntimeError.new("pointer already freed") unless @ptr
        @autorelease = false
        @ptr = nil
        @proc = nil
      end

Notice that the bitmap was not freed.  Worse, the bitmap will never be
freed because @autorelease is now false. Take a look at the finalizer:

    class DefaultReleaser < Releaser
      def call(*args)
        @proc.release(@ptr) if @autorelease && @ptr
      end
    end

I think the free method should be:

      def free
        raise RuntimeError.new("pointer already freed") unless @ptr
        @proc.release(@ptr)
        @autorelease = false
        @ptr = nil
        @proc = nil
      end

Thanks,

Charlie