Ruby 1.9.2-p-180因“非法指令”或“堆栈级别太深(SystemStackError)”而失败

时间:2011-03-22 03:56:48

标签: ruby rvm

行为:Ruby 1.9.2p180因“非法指令”失败而没有其他细节。 Ruby 1.9.1p378运行完全没有任何问题。

失败发生在行pin = fronto.index(k)中,仅在一些迭代中发生。

frominto都是对象数组,by是该对象的属性(x或y)。

代码:

  def add_from_to_by from, into, by
    nto = into.sort_by{|k| k.send(by)}
    fronto = (from + nto).sort_by{|k| k.send(by)}
    dict = {}
    nto.each{|k| dict[k] = []}
    nto.each do |k|
      pin = fronto.index(k)
      up = pin+1
      down = pin-1
      while up < fronto.length and ((fronto[pin].send(by)) - (fronto[up].send(by))).abs <= $sensor_range
        if fronto[up].kind_of?(BasicNode) then 
          dict[k].push(fronto[up]) 
        end
        up += 1
      end
      while down >= 0 and ((fronto[pin].send(by)) - (fronto[down].send(by))).abs <= $sensor_range
        if fronto[down].kind_of?(BasicNode)
          dict[k].push(fronto[down])
        end
        down -= 1
      end
    end
    return dict
  end 

我正在使用rvm来管理Mac 10.6.6上的ruby版本。知道为什么会这样吗?

REVISION:

如果上面的代码减少到:

def add_from_to_by from, into, by
        nto = into.sort_by{|k| k.send(by)}
        fronto = (from + nto).sort_by{|k| k.send(by)}
        dict = {}
        nto.each{|k| dict[k] = []}
        x = nto.select{|k| !fronto.include?(k)}
end

这会重现最后一行的错误。 在输入中,崩溃,进入和离开是不相交的点集。应该有效的类定义是:

class BasicNode
    attr_reader :x, :y
    def initialize x, y
        @x = x
        @y = y
    end
end

其中x和y是数字。在崩溃的测试中,into中有15个节点,from中有5个节点。

编辑:

当我稍微隔离代码时,我确实得到stack level too deep (System Stack Error)。但是,我不确定为什么会这样,因为在此代码或数组索引的C实现中没有递归调用。

ADDENDUM:此问题的完整源代码可在此处找到:http://code.google.com/p/graphcomplexity/

repository:rvertex 分支:默认 测试文件:test / test_deeps_hypersim.rb

1 个答案:

答案 0 :(得分:2)

在linux上使用1.9.2-p180,我无法重现你的问题。这是我的测试设置:

$sensor_range=5
list1=Array.new(1000) {|i| BasicNode.new(rand(100),rand(100))}
list2=Array.new(1000) {|i| BasicNode.new(rand(100),rand(100))}
res=add_from_to_by(list1,list2,:x);

你的错误是否仍然出现在那套指令中?如果您仍然遇到错误,但没有收到这些说明,您是否可以提供一些示例数据和函数调用来说明问题? (如果它很大,你可以使用像pastebin.com这样的服务)


另外,我不是100%确定它是否完全相同,但这可能是一种更直接的方式来编写相同的函数(您的程序可能更容易使用更简单的代码进行调试):

def add_from_to_modified(from,into,sensor_range,&block)
  into.inject({}) do |result,key|
    result.merge({key=>(into+from).select {|check| (yield(check)-yield(key)).abs <= sensor_range}})
  end
end

add_from_to_modified(list1,list2,5,&:x)

如果效率太低,可以用循环外的yield()来重写它。此实现还允许您传递任意块而不仅仅是一个函数来调用

add_from_to_modified(list1,list2,5) {|node| node.x*3-node.y}