关于从方法返回的超出范围的 FFI MemoryPointer 的问题

huangapple go评论96阅读模式
英文:

Question about out-of-scope FFI MemoryPointer that is returned from a method

问题

在这种情况下,内部在foobar方法中创建的MemoryPointer何时被垃圾回收呢?它是在foobar方法中MemoryPointer变量离开作用域时,还是在testing方法中ab这些本地变量(它们引用了从foo/bar方法返回的MemoryPointer)离开作用域时?

在这种情况下,MemoryPointer对象将在以下情况被垃圾回收:

  1. 对于foo方法:MemoryPointer对象将在foo方法中的result变量离开作用域时被垃圾回收。

  2. 对于bar方法:MemoryPointer对象将在bar方法中的value变量和simple_struct对象离开作用域时被垃圾回收。

  3. 对于testing方法:MemoryPointer对象将在testing方法中的变量ab离开作用域时被垃圾回收。这是因为在testing方法中,变量ab分别引用了foobar方法返回的MemoryPointer对象,当这些变量离开作用域时,没有更多的引用指向这些对象,它们就会变得可垃圾回收。

总之,在Ruby中,当没有引用指向一个对象时,它就会变得可垃圾回收。所以,在这种情况下,MemoryPointer对象将在最后一次引用它的变量离开作用域时被垃圾回收。

英文:

Let's say I have the following ruby code that uses FFI library:

  1. class SimpleStruct < FFI::Struct
  2. layout :value, :pointer
  3. end
  4. class Test1
  5. def self.foo(s)
  6. result = FFI::MemoryPointer.from_string(s)
  7. result
  8. end
  9. def self.bar(s)
  10. simple_struct = SimpleStruct.new
  11. value = FFI::MemoryPointer.from_string(s)
  12. simple_struct[:value] = value
  13. simple_struct
  14. end
  15. end
  16. class Test2
  17. def self.testing
  18. a = Test1.foo('test')
  19. b = Test1.bar('test')
  20. puts a.read_string, b[:value].read_string
  21. end
  22. end

The FFI wiki mentions When a MemoryPointer goes out of scope, the memory is freed up as part of the garbage collection process. In the Test1 class above, foo method returns a MemoryPointer and bar method returns an FFI struct that holds MemoryPointer. The testing method in Test2 class calls these methods and stores the returned values in variable a and b respectively.

My question is when the MemoryPointer created inside foo and bar method will be garbage collected in this case? Is it when the MemoryPointer variable goes out of scope in foo and bar methods or when the local variable a or b (that references the MemoryPointer returned from the foo/bar methods) goes out of scope in testing method?

答案1

得分: 1

我相信 FFI::Struct#[]= 处理了这个问题。我没有在源代码中检查它,但我在您的代码中添加了一些检查,看起来是这样的。

  1. require 'ffi'
  2. class SimpleStruct < FFI::Struct
  3. layout :value, :pointer
  4. end
  5. class Test1
  6. def self.foo(s)
  7. puts "foo is called"
  8. result = FFI::MemoryPointer.from_string(s)
  9. ObjectSpace.define_finalizer(result, proc { puts "foo result is garbage collected" })
  10. result
  11. end
  12. def self.bar(s)
  13. puts "bar is called"
  14. simple_struct = SimpleStruct.new
  15. ObjectSpace.define_finalizer(s, proc { puts "bar result is garbage collected" })
  16. value = FFI::MemoryPointer.from_string(s)
  17. ObjectSpace.define_finalizer(s, proc { puts "bar result[:value] is garbage collected" })
  18. simple_struct[:value] = value
  19. simple_struct
  20. end
  21. def self.baz(s)
  22. puts "baz is called"
  23. simple_struct = {}
  24. ObjectSpace.define_finalizer(s, proc { puts "baz result is garbage collected" })
  25. value = FFI::MemoryPointer.from_string(s)
  26. ObjectSpace.define_finalizer(s, proc { puts "baz result[:value] is garbage collected" })
  27. simple_struct[:value] = value
  28. simple_struct
  29. end
  30. end
  31. class Test2
  32. def self.testing
  33. puts "testing is started"
  34. a = Test1.foo('foo')
  35. b = Test1.bar('bar')
  36. c = Test1.baz('baz')
  37. puts a.read_string, b[:value].read_string, c[:value].read_string
  38. puts "testing is finished"
  39. end
  40. end
  41. GC.stress
  42. Test2.testing
  43. # testing is started
  44. # foo is called
  45. # bar is called
  46. # baz is called
  47. # foo
  48. # bar
  49. # baz
  50. # testing is finished
  51. # baz result is garbage collected
  52. # baz result[:value] is garbage collected
  53. # bar result is garbage collected
  54. # bar result[:value] is garbage collected
  55. # foo result is garbage collected

只有当结构被垃圾回收时,指针才会被垃圾回收,就像哈希表一样。

英文:

I believe FFI::Struct#[]= takes care of this. I didn't check it in the sources, but I've added some checks into your code and it looks so.

  1. require &#39;ffi&#39;
  2. class SimpleStruct &lt; FFI::Struct
  3. layout :value, :pointer
  4. end
  5. class Test1
  6. def self.foo(s)
  7. puts &quot;foo is called&quot;
  8. result = FFI::MemoryPointer.from_string(s)
  9. ObjectSpace.define_finalizer(result, proc { puts &quot;foo result is garbage collected&quot; })
  10. result
  11. end
  12. def self.bar(s)
  13. puts &quot;bar is called&quot;
  14. simple_struct = SimpleStruct.new
  15. ObjectSpace.define_finalizer(s, proc { puts &quot;bar result is garbage collected&quot; })
  16. value = FFI::MemoryPointer.from_string(s)
  17. ObjectSpace.define_finalizer(s, proc { puts &quot;bar result[:value] is garbage collected&quot; })
  18. simple_struct[:value] = value
  19. simple_struct
  20. end
  21. def self.baz(s)
  22. puts &quot;baz is called&quot;
  23. simple_struct = {}
  24. ObjectSpace.define_finalizer(s, proc { puts &quot;baz result is garbage collected&quot; })
  25. value = FFI::MemoryPointer.from_string(s)
  26. ObjectSpace.define_finalizer(s, proc { puts &quot;baz result[:value] is garbage collected&quot; })
  27. simple_struct[:value] = value
  28. simple_struct
  29. end
  30. end
  31. class Test2
  32. def self.testing
  33. puts &quot;testing is started&quot;
  34. a = Test1.foo(&#39;foo&#39;)
  35. b = Test1.bar(&#39;bar&#39;)
  36. c = Test1.baz(&#39;baz&#39;)
  37. puts a.read_string, b[:value].read_string, c[:value].read_string
  38. puts &quot;testing is finished&quot;
  39. end
  40. end
  41. GC.stress
  42. Test2.testing
  43. # testing is started
  44. # foo is called
  45. # bar is called
  46. # baz is called
  47. # foo
  48. # bar
  49. # baz
  50. # testing is finished
  51. # baz result is garbage collected
  52. # baz result[:value] is garbage collected
  53. # bar result is garbage collected
  54. # bar result[:value] is garbage collected
  55. # foo result is garbage collected

A pointer is only garbage collected when the struct is garbage-collected, as is the case with a hash.

huangapple
  • 本文由 发表于 2023年6月15日 19:33:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/76482044.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定