Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails Rails内存泄漏:持有实例引用的控制器类_Ruby On Rails_Ruby_Actioncontroller - Fatal编程技术网

Ruby on rails Rails内存泄漏:持有实例引用的控制器类

Ruby on rails Rails内存泄漏:持有实例引用的控制器类,ruby-on-rails,ruby,actioncontroller,Ruby On Rails,Ruby,Actioncontroller,我在Rails 4.2.6应用程序中有内存泄漏。控制器将一个大的GaragesPresenter对象分配为实例变量,请求完成后应取消引用并进行垃圾收集。然而,我看到这种情况从未发生过 def show @garage = GaragesPresenter.new(@garage, view_context) respond_to do |format| format.html end end 我看到对GaragesPresenter实例的引用由GaragesControll

我在Rails 4.2.6应用程序中有内存泄漏。控制器将一个大的
GaragesPresenter
对象分配为实例变量,请求完成后应取消引用并进行垃圾收集。然而,我看到这种情况从未发生过

def show
  @garage = GaragesPresenter.new(@garage, view_context)
  respond_to do |format|
    format.html
  end
end
我看到对
GaragesPresenter
实例的引用由
GaragesController
实例持有,对该实例的引用由
GaragesController
类持有。在请求完成并且调用了
GC.start
之后很久,这种情况就会出现为什么
GaragesController
类持有对实例的引用?

我之所以知道这一点,是因为我使用以下设置了堆转储:

require 'objspace'
...
GC.start
file = File.open("/tmp/dumpfile", 'w')
ObjectSpace.dump_all(output: file)
在生成的文件中,我看到以下三个对象:

以下对象是非常大的GaragesPresenter:

{“地址”:“0x7fd077217e20”,“类型”:“对象”,“类”:“0x7fd074a04618”,“ivars”:7,“引用”:[“0x7fd0772bf940”,“0x7fd077711480”,“0x7fd077748188”,“0x7fd077772898”,“0x7fd07720c778”,“0x7fd0771ef8d0”,“0x7fd0771ef8d0”],“文件”:“/Users/dyoung/workspace/communible/site-app/app/controllers/garages\u-controller.rb”,“行”:“新方法”,“generation”:35,“memsize”:56,“flags”:{“wb_protected”:true,“old”:true,“marked”:true}

对上述对象的引用由GaragesController实例持有(由于show方法将presenter分配为实例变量,这是预期的):

{“地址”:“0x7fd0727559f0”,“类型”:“对象”,“类”:“0x7fd0727865a0”,“ivars”:22,“引用”:[“0x7fd0727558b0”,“0x7fd072755888”,“0x7fd072755838”,“0x7fd0732400e0”,“0x7fd072754a50”,“0x7fd0734c5658”,“0x7fd07704e878”,“0x7fd0732ab020”,“0x7fd072785ee8”,“0x7fd077217e20”,“0x7FD077110”,“0x7FD07720”,“0x7FD07720”,“0x7D0”,“0x7FD07827D0文件”:“:“/Users/dyoung/.rvm/gems/ruby-2.1.0/gems/actionpack-4.2.6/lib/action\u controller/metal.rb”,“line”:237,“method”:“new”,“generation”:35,“memsize”:176,“flags”:{“wb\u protected”:true,“old”:true,“marked”:true}

GaragesController类持有对上述GaragesController实例的引用,这可能会阻止garabage收集。为什么??

{“地址”:“0x7fd0727865a0”,“类型”:“类”,“类”:“0x7fd0726a7260”,“名称”:“GaragesController”,“引用”:[“0x7fd0727559f0”,“0x7fd0726a72b0”],“文件”:“/Users/dyoung/.rvm/gems/ruby-2.1.0/gems/activesupport-4.2.6/lib/active_support/callbacks.rb”,“行”{435,“方法”:“instance_exec”,“generation”:35,“memsize”:672,“flags”:”wb_protected:true,“old:true”,marked:true}

您需要使用

弱引用类,允许引用对象 垃圾收集。WeakRef的使用方式可能与它所收集的对象完全相同 参考资料

用例中使用了两个对象引用。第一个是主引用,第二个是弱引用。在使用第一个主链接之前,不会对对象进行垃圾收集。在对象中使用主链接(通用变量),该对象的生存时间与我们需要的被引用对象相同或更长。而在被引用对象内部使用弱链接

这是一个相应的实践,在另一种语言中也有垃圾回收器,例如在Perl中。C++库对内存管理策略有太多的解决方案。垃圾收集器不能清除垃圾(对象)。当它们在使用中时。如果对象引用另一个对象,而另一个引用第一个对象,这意味着两者都在使用中。因此,它不是垃圾-这对于“垃圾收集器意见”很有用。但实际上它是垃圾-这是内存泄漏


对象引用图不能有循环或循环。如果我们需要在对象引用图中形成循环或循环的引用,我们需要在每个引用图中至少使用一个准切割弱引用。

GaragesPresenter
包含对
视图上下文的引用

@garage = GaragesPresenter.new(@garage, view_context)
view\u context
返回包含对调用控制器的
self
的引用的:

# File actionview/lib/action_view/rendering.rb, line 71
def view_context
  view_context_class.new(view_renderer, view_assigns, self)
end

似乎
[WeakRef](ruby doc.org/stdlib-1.9.3/libdoc/WeakRef/rdoc/WeakRef.html)
能帮上忙谢谢你的提示。但是我不希望我的
@garage
对象在我使用完之前被垃圾收集。似乎如果我使用
WeakRef
,那么它有可能在控制器方法完成之前被垃圾收集。我错了吗?总是可以的。我对答案做了一些改进。使用master链接到一个不进行垃圾收集的地方。是的,这似乎可以起到改进的作用。但这似乎与我在方法末尾简单地设置
@garage=nil
具有相同的效果。虽然这两种方法都是合理的解决方法,但我的理解是,我不需要在Rails中这样做。我会这样做首先,我想知道我做错了什么,如果有什么的话,这是导致这种意外行为的原因。这不是解决办法。这是唯一的办法。我会尝试打开完整的。谢谢。但这不会阻止垃圾收集,对吧?我想演示者保留对控制器实例的引用是可以的,因为两个对象都应该只存在于st表示请求的生存期。在请求结束后,这两个对象都应该有资格进行垃圾收集。不应该这样做,除非控制器或演示器中有什么东西在保持,在这种情况下,这两个对象都将保持存在。我将仔细查看是否有任何常量发生了变化。是的,在我的情况下,我有证据表明omething正在保存对控制器的引用。您所说的“是否有任何常量正在发生变异”是什么意思?常量不会被垃圾清理,因此如果您在常量中有数组或哈希,该数组/哈希的内容将永远不会超出范围。这可能不明显,例如
values=DEFAULT\u values;values
# File actionview/lib/action_view/rendering.rb, line 71
def view_context
  view_context_class.new(view_renderer, view_assigns, self)
end