You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ruby FFI中返回的MemoryPointer何时会被垃圾回收?

Ruby FFI中MemoryPointer的垃圾回收时机分析

示例代码

class SimpleStruct < FFI::Struct
  layout :value, :pointer
end

class Test1
  def self.foo(s)
    result = FFI::MemoryPointer.from_string(s)

    result
  end

  def self.bar(s)
    simple_struct = SimpleStruct.new
    value = FFI::MemoryPointer.from_string(s)
    simple_struct[:value] = value

    simple_struct
  end
end


class Test2
  def self.testing
    a = Test1.foo('test')
    b = Test1.bar('test')

    puts a.read_string, b[:value].read_string
  end
end

问题背景

FFI官方维基提到:When a MemoryPointer goes out of scope, the memory is freed up as part of the garbage collection process(当MemoryPointer超出作用域时,其占用内存会作为垃圾回收的一部分被释放)。针对上述代码,疑问是:Test1的foo、bar方法内创建的MemoryPointer,到底是在方法内的变量超出作用域时被回收,还是在Test2#testing方法里的a、b变量超出作用域时才被回收?

解答

首先要明确:Ruby的垃圾回收机制是基于对象可达性的,而非单纯的词法作用域。FFI的MemoryPointer本质是Ruby对象,完全遵循Ruby的GC规则,维基里的“out of scope”实际指的是该MemoryPointer对象不再被任何Ruby对象引用的状态。

分两种场景说明:

  1. foo方法返回的MemoryPointer
    foo方法内创建的result(MemoryPointer对象)被作为返回值赋值给了testing方法里的a变量。此时,尽管foo方法执行完毕后,内部的result变量已经出了词法作用域,但它指向的MemoryPointer对象还被a引用着,所以不会被GC回收。只有当a变量超出testing方法的作用域,且没有其他任何Ruby对象再引用这个MemoryPointer时,GC才会回收该对象,同时释放对应的内存。

  2. bar方法内创建的MemoryPointer
    bar方法内创建的value(MemoryPointer对象)被赋值给了simple_struct的:value字段,随后这个结构体被返回给testing方法的b变量。只要b变量还存在(或者结构体本身还有其他引用),这个MemoryPointer就会被结构体持有引用,因此不会被回收。只有当b超出作用域,且没有其他引用指向该结构体,同时这个MemoryPointer也没有其他额外引用时,GC才会回收它并释放内存。

简单总结:方法内的MemoryPointer变量出作用域并不会直接触发回收,只有当对应的MemoryPointer对象失去所有可达引用(比如外部的a、b也不再引用它)时,才会被Ruby GC处理,进而释放内存。

内容的提问来源于stack exchange,提问作者null

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 02:12:47