- xml - AJAX/Jquery XML 解析
- 具有多重继承的 XML 模式
- .net - 枚举序列化 Json 与 XML
- XML 简单类型、简单内容、复杂类型、复杂内容
我正在通过 Ferret(Lucene 的 Ruby 端口)代码解决问题一个错误。 Ferret 代码主要是 Ruby 的 C 扩展。我遇到了垃圾收集器的一些问题。我设法修复了它,但我不完全理解我的修复=)我希望有人更深入了解 Ruby 和 C 扩展(这是我使用 Ruby 的第三天)可以精心制作的。谢谢。
情况是这样的:
在 Ferret C 代码的某个地方,我将“ token ”返回到 Ruby 领域。代码看起来像
static VALUE get_token (...)
{
...
RToken *token = ALLOC(RToken);
token->text = rb_str_new2("some text");
return Data_Wrap_Struct(..., &frt_token_mark, &frt_token_free, token);
}
frt_token_mark 调用 rb_gc_mark(token->text) 和 frt_token_free只需使用 free(token) 释放 token
在 Ruby 中,此代码与以下内容相关:
token = @input.next
基本上,@input 被设置为某个对象,调用它的 next 方法触发 get_token C 调用,它返回一个 token 对象。
在 Ruby 领域,我会做类似 w = token.text.scan('\w+') 的事情
当我在 while 1 循环中运行此代码(以隔离我的问题)时,在某个点(大约当我的 ruby 进程内存占用达到 256MB 时,可能是一些 GC 阈值),Ruby 死于类似这样的错误
在终止对象上调用的扫描方法
或者只是核心转储。我的猜测是 token.text 被垃圾收集了。
我对 Ruby C 扩展的了解还不够,不知道会发生什么Data_Wrap_Struct 返回对象。在我看来,Ruby 中的任务land, token =, 应该创建对它的引用。
我的“解决方法”/“修复”是在@input 引用的对象,并将标记文本存储在那里,以获得对它的额外引用。所以 C 代码看起来像
RToken *token = ALLOC(RToken);
token->text = rb_str_new2(tk->text);
/* added code: prevent garbage collection */
rb_ivar_set(input, id_curtoken, token->text);
return Data_Wrap_Struct(cToken, &frt_token_mark, &frt_token_free, token);
所以现在我在输入实例变量中创建了一个“curtoken”,并且在那里保存了文本的副本......我已经注意删除/删除@input 类的自由回调中的 this 引用。
使用这段代码,它的工作原理是我不再得到终止的对象错误。
这个修复对我来说似乎很有意义——它在 curtoken 中保留了一个额外的引用到 token.text 字符串,因此不会删除 token.text 的实例直到下一次 @input.next 被调用(此时一个不同的token.text 替换了 curtoken 中的旧值。
我的问题是:为什么以前不行?不应该Data_Wrap_Structure 返回一个对象,当在 Ruby land 中分配时,有一个有效的引用并且没有被 Ruby 删除?
谢谢。
最佳答案
当调用 Ruby 垃圾收集器时,它有一个标记阶段和一个清除阶段。标记阶段通过标记标记系统中的所有对象:
以及一些对本次讨论不重要的其他对象。然后,扫描阶段会销毁所有不可访问的对象(即未标记的对象)。
Data_Wrap_Struct 返回一个对象的引用。只要该引用可用于 ruby 代码(例如,存储在局部变量中)或在堆栈上(由局部 C 变量引用),就不应清除该对象。
从您发布的内容看来,token->text 正在被垃圾收集。但为什么它会被收集起来?它不能被标记。 Token 对象本身是否被标记?如果是,那么 token->text 应该被标记。尝试在 token 的标记功能中设置断点或打印消息以查看。
如果 token 没有被标记,那么下一步就是找出原因。如果它被标记了,那么下一步就是弄清楚为什么 text() 方法返回的字符串被清除了(也许它不是被标记的同一个对象)。
此外,您确定是 token 的文本成员导致了异常吗?看着:
http://github.com/dbalmain/ferret/blob/master/ruby/ext/r_analysis.c
我看到 token 和 token 流都有 text() 方法。 TokenStream 结构不持有对其文本对象的引用(它不能,因为它是一个不了解 ruby 的 C 结构)。因此,包装 C 结构的 Ruby 对象需要保存引用(这是通过 rb_ivar_set 完成的)。
RToken 结构不需要这样做,因为它在其标记函数中标记了它的文本成员。
还有一件事:您可以通过在循环中显式调用 GC.start 来重现此错误,而不必分配垃圾收集器启动的那么多对象。这不会解决问题,但可能会进行诊断更简单。
关于ruby - 使用 Ruby C Extension 进行垃圾收集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2003885/
以下是一个非常简单的ruby服务器。 require 'socket' local_socket = Socket.new(:INET, :STREAM) local_addr = Socket.
我正在使用 OS X(使用 bash),并且是 unix 的新手。我想知道是否可以修改一些文件以便运行 ruby 程序,我不需要“ruby file.rb”,而是可以运行“ruby.rb”。 有理
我在用 Ruby 替换字符串时遇到一些问题。 我的原文:人之所为不如兽之所为。 我想替换为:==What== human does is not like ==what== animal does.
我想在一个循环中从 Ruby 脚本做这样的事情: 写一个文件a.rb(每次迭代都会改变) 执行系统(ruby 'a.rb') a.rb 将带有结果的字符串写入文件“results” a.rb 完成并且
我的问题是尝试创建一个本地服务器,以便我可以理解由我的新团队开发的应用程序。我的问题是我使用的是 Ruby 2.3.3,而 Gemfile 需要 2.3.1。我无法编辑 Gemfile,因为我被告知很
我有一个使用 GLI 框架用 Ruby 编写的命令行实用程序。我想在我的主目录中配置我的命令行实用程序,使用 Ruby 本身作为 DSL 来处理它(类似于 Gemfile 或 Rakefile)。 我
我的 Rails 应用 Controller 中有这段代码: def delete object = model.datamapper_class.first(:sourced_id =>
我正在寻找的解析器应该: 对 Ruby 解析友好, 规则设计优雅, 产生用户友好的解析错误, 用户文档的数量应该比计算器示例多, UPD:允许在编写语法时省略可选的空格。 快速解析不是一个重要的特性。
我刚开始使用 Ruby,听说有一种“Ruby 方式”编码。除了 Ruby on Rails 之外,还有哪些项目适合学习并被认可且设计良好? 最佳答案 Prawn被明确地创建为不仅是一个该死的好 PDF
我知道之前有人问过类似的问题,但是我该如何构建一个无需在前面输入“ruby”就可以在终端中运行的 Ruby 文件呢? 这里的最终目标是创建一个命令行工具包类型的东西。现在,为了执行我希望用户能够执行的
例如哈希a是{:name=>'mike',:age=>27,:gender=>'male'}哈希 b 是 {:name=>'mike'} 我想知道是否有更好的方法来判断 b 哈希是否在 a 哈希内,而
我是一名决定学习 Ruby 和 Ruby on Rails 的 ASP.NET MVC 开发人员。我已经有所了解并在 RoR 上创建了一个网站。在 ASP.NET MVC 上开发,我一直使用三层架构:
最近我看到 Gary Bernhardt 展示了他用来在 vim 中执行 Ruby 代码的 vim 快捷方式。捷径是 :map ,t :w\|:!ruby %. 似乎这个方法总是执行系统 Rub
在为 this question about Blue Ruby 选择的答案中,查克说: All of the current Ruby implementations are compiled to
我有一个 Ruby 数组 > list = Request.find_all_by_artist("Metallica").map(&:song) => ["Nothing else Matters"
我在四舍五入时遇到问题。我有一个 float ,我想将其四舍五入到小数点后的百分之一。但是,我只能使用 .round ,它基本上将它变成一个 int,意思是 2.34.round # => 2. 有没
我使用 ruby on rails 编写了一个小型 Web 应用程序,它的主要目的是上传、存储和显示来自 xml(文件最多几 MB)文件的结果。运行大约 2 个月后,我注意到 mongrel 进程
我们如何用 Ruby 转换像这样的字符串: 𝑙𝑎𝑡𝑜𝑟𝑟𝑒 收件人: Latorre 最佳答案 s = "𝑙𝑎𝑡𝑜𝑟𝑟𝑒" => "𝑙𝑎𝑡𝑜𝑟𝑟𝑒" s.u
通过 ruby monk 时,他们偶尔会从左侧字段中抛出一段语法不熟悉的代码: def compute(xyz) return nil unless xyz xyz.map {|a,
不确定我做错了什么,但我似乎弄错了。 问题是,给你一串空格分隔的数字,你必须返回最大和最小的数字。 注意:所有数字都是有效的 Int32,不需要验证它们。输入字符串中始终至少有一个数字。输出字符串必须
我是一名优秀的程序员,十分优秀!