为什么我会遇到分段错误(qtruby)?

为什么我会遇到分段错误(qtruby)?,ruby,segmentation-fault,qtruby,Ruby,Segmentation Fault,Qtruby,我在访问类变量(一个Qt::Actions的数组)时遇到了分段错误的问题,我一直试图将其缩减到一个最小的代码示例,以复制该问题: #!/usr/bin/ruby require 'Qt4' require 'rufus/scheduler' app = Qt::Application.new(ARGV) class ManagerWidget < Qt::Widget signals 'changed(int)' def initialize sup

我在访问类变量(一个
Qt::Action
s的数组)时遇到了分段错误的问题,我一直试图将其缩减到一个最小的代码示例,以复制该问题:

#!/usr/bin/ruby

require 'Qt4'
require 'rufus/scheduler'

app = Qt::Application.new(ARGV)

class ManagerWidget < Qt::Widget
    signals 'changed(int)'

    def initialize
        super(nil)

        max_index = 2
        next_index = 0

        scheduler = Rufus::Scheduler.start_new
        scheduler.every '10s' do
            emit changed(next_index)
            if next_index < max_index - 1
                next_index += 1
            else
                next_index = 0
            end
        end
    end
end

class Tray < Qt::Widget
    def initialize
        super(nil)

        tray = Qt::SystemTrayIcon.new
        manager_widget = ManagerWidget.new
        menu = Qt::Menu.new

        tray_icon = Qt::Icon.new("./icons/Gnome-Preferences-Desktop-Wallpaper-64.png")

        actions = []
        manager_widget.connect(SIGNAL('changed(int)')) do |i|
            puts "changed #{i}"
            actions[i].text = '...' if actions && actions[i]
        end

        2.times do |i|
            sub_menu = Qt::Menu.new("#{i + 1}")
            actions[i] = sub_menu.add_action('x')
            menu.add_menu(sub_menu)
        end

        tray.icon = tray_icon
        tray.context_menu = menu

        tray.show
    end
end

Tray.new
app.exec
似乎有必要使用子菜单来触发此问题-至少将操作添加到托盘菜单本身运行了相当长的一段时间,没有出现问题(我将其保留了10倍以上,直到上面的代码出现错误为止)

Ruby版本:
Ruby 1.9.3p0(2011-10-30修订版33570)[x86\u 64-linux]

Qt版本:
4.8.1

绑定版本:
qtbindings(4.8.3.0)

Linux版本:
Ubuntu 12.04

另一个奇怪的行为是,
put
调用的输出有时会立即显示在控制台中,有时它只在我将鼠标移到托盘图标上时打印

我甚至不知道从哪里开始追踪,所以非常感谢您的任何意见

更新:我已经离开这个有一段时间了,因为我不能得到更多。我试着重新开始,但我仍然遇到同样的问题。我已经深入研究了这个问题,因为它说“缺少方法”,所以我开始打印这个类,以确保我确实看到了一个Qt::Action(我是),然后根据
actions[0]。methods
,哪些方法可用

。方法
输出:

[:setShortcut, :shortcut=, :qobject_cast, :inspect, :pretty_print, :className,
:class_name, :inherits, :findChildren, :find_children, :findChild, :find_child,
:connect, :method_missing, :const_missing, :dispose, :isDisposed, :disposed?,
:qVariantValue, :qVariantFromValue, :**, :+, :~, :-@, :-, :*, :/, :%, :>>,
:<<, :&, :^, :|, :<, :<=, :>, :>=, :==, :is_a?, :kind_of?, :methods,
:protected_methods, :public_methods, :singleton_methods, :qDebug, :qFatal,
:qWarning, :SIGNAL, :SLOT, :emit, :QT_TR_NOOP, :QT_TRANSLATE_NOOP, :nil?, :===,
:=~, :!~, :eql?, :hash, :<=>, :class, :singleton_class, :clone, :dup,
:initialize_dup, :initialize_clone, :taint, :tainted?, :untaint, :untrust,
:untrusted?, :trust, :freeze, :frozen?, :to_s, :private_methods,
:instance_variables, :instance_variable_get, :instance_variable_set,
:instance_variable_defined?, :instance_of?, :tap, :send, :public_send,
:respond_to?, :respond_to_missing?, :extend, :display, :method, :public_method,
:define_singleton_method, :object_id, :to_enum, :enum_for, :equal?, :!, :!=,
:instance_eval, :instance_exec, :__send__, :__id__, "blockSignals", "children",
"connect", "deleteLater", "disconnect", "dumpObjectInfo", "dumpObjectTree",
"dynamicPropertyNames", "event", "eventFilter", "inherits", "installEventFilter",
"widgetType?", "killTimer", "metaObject", "moveToThread", "objectName", "parent",
"property", "qt_metacall", "qt_metacast", "removeEventFilter", "objectName=",
"parent=", "setProperty", "setUserData", "signalsBlocked", "startTimer",
"thread", "userData", "actionGroup", "activate", "associatedGraphicsWidgets",
"associatedWidgets", "autoRepeat", "data", "font", "hover", "icon", "iconText",
"checkable?", "checked?", "enabled?", "iconVisibleInMenu?", "separator?",
"visible?", "menu", "menuRole", "parentWidget", "priority", "actionGroup=",
"autoRepeat=", "checkable=", "checked=", "data=", "disabled=", "enabled=",
"font=", "icon=", "iconText=", "iconVisibleInMenu=", "menu=", "menuRole=",
"priority=", "separator=", "shortcut=", "shortcutContext=", "shortcuts=",
"softKeyRole=", "statusTip=", "text=", "toolTip=", "visible=", "whatsThis=",
"shortcut", "shortcutContext", "shortcuts", "showStatusText", "softKeyRole",
"statusTip", "text", "toggle", "toolTip", "trigger", "whatsThis"]

对Manager.new的调用初始化该对象,并在最后调用状态更改的侦听器,这反过来调用
更新
过程,该过程访问
操作
数组。在这个阶段,所有这些都应该在同一个线程中,除了实际创建
QT::Action
之外,这些行都不依赖于QT。我已经删除了Rufus调度,并将其替换为
QTimer
,但这还不足以成为问题。

有一件事我看不到您尝试过,那就是使用更新版本的ruby。p0似乎潜在地充满了问题


Ruby 1.9.3-p392是1.9.3的最新版本。

我花了太多时间在这上面,却不知道为什么会发生这种情况(多亏了那些试图提供帮助的人,但不幸的是它没有解决问题)。因此,我将我的工作放在这里,以防其他人有类似问题:


我已经放弃了数组,而是将要使用它的代码包装在一个
Proc
中,我在先前填充数组的循环中创建了这个
Proc。由于在此循环中创建的
Proc
可以直接访问相关变量,因此不再需要将其存储在数组中并在以后检索。它提出了一个或两个自己的问题,因为
Proc
中的代码现在每个
SIGNAL
操作执行一次,而不是让一个代码块执行所有相关操作,但它们更容易处理。

您确定可以这样使用qtbindings吗?qtbindings是线程安全的吗?你知道Rufus创建了一个新的Ruby线程吗?我认为一旦你进入Qt世界,你需要使用Qt定时器,而不是Ruby定时器。也就是说,要触发
emit
,你可能需要使用类似
QTimer
的东西来代替Rufus。@Casper,我不知道,我不知道Rufus创建了一个新的Ruby线程,不。即使它不是线程安全的,失败的方式仍然很奇怪(仍然只有一个线程在任何时候都可以访问它,而且该引用似乎还可以,因为我可以打印出一些关于它的信息)。我仍在尝试学习QT,但没有意识到我可以使用QTimer,我会尝试一下,谢谢。@Casper这似乎不是问题所在,失败的代码根本不是由Rufus调度程序运行的(因为它在初始化过程中失败,这应该仍然是主线程)。如果这有助于澄清问题,我已经在问题中添加了更多关于它的细节。我不知道这是否相关,但我的小部件的
initialize
方法似乎被执行了两次。我不知道是什么原因,或者为什么。我当然在我自己的代码中找不到任何对它的引用。因为我使用Mint软件包manag安装了ruby呃,它会不时更新,目前在
1.9.3p194
上。我想不是最新的,但在我处理这个问题的时候,我已经尝试了至少几个不同的补丁版本。不过,这是一个很好的建议,我会看看是否有时间在某个时候手动安装最新版本。
[:setShortcut, :shortcut=, :qobject_cast, :inspect, :pretty_print, :className,
:class_name, :inherits, :findChildren, :find_children, :findChild, :find_child,
:connect, :method_missing, :const_missing, :dispose, :isDisposed, :disposed?,
:qVariantValue, :qVariantFromValue, :**, :+, :~, :-@, :-, :*, :/, :%, :>>,
:<<, :&, :^, :|, :<, :<=, :>, :>=, :==, :is_a?, :kind_of?, :methods,
:protected_methods, :public_methods, :singleton_methods, :qDebug, :qFatal,
:qWarning, :SIGNAL, :SLOT, :emit, :QT_TR_NOOP, :QT_TRANSLATE_NOOP, :nil?, :===,
:=~, :!~, :eql?, :hash, :<=>, :class, :singleton_class, :clone, :dup,
:initialize_dup, :initialize_clone, :taint, :tainted?, :untaint, :untrust,
:untrusted?, :trust, :freeze, :frozen?, :to_s, :private_methods,
:instance_variables, :instance_variable_get, :instance_variable_set,
:instance_variable_defined?, :instance_of?, :tap, :send, :public_send,
:respond_to?, :respond_to_missing?, :extend, :display, :method, :public_method,
:define_singleton_method, :object_id, :to_enum, :enum_for, :equal?, :!, :!=,
:instance_eval, :instance_exec, :__send__, :__id__, "blockSignals", "children",
"connect", "deleteLater", "disconnect", "dumpObjectInfo", "dumpObjectTree",
"dynamicPropertyNames", "event", "eventFilter", "inherits", "installEventFilter",
"widgetType?", "killTimer", "metaObject", "moveToThread", "objectName", "parent",
"property", "qt_metacall", "qt_metacast", "removeEventFilter", "objectName=",
"parent=", "setProperty", "setUserData", "signalsBlocked", "startTimer",
"thread", "userData", "actionGroup", "activate", "associatedGraphicsWidgets",
"associatedWidgets", "autoRepeat", "data", "font", "hover", "icon", "iconText",
"checkable?", "checked?", "enabled?", "iconVisibleInMenu?", "separator?",
"visible?", "menu", "menuRole", "parentWidget", "priority", "actionGroup=",
"autoRepeat=", "checkable=", "checked=", "data=", "disabled=", "enabled=",
"font=", "icon=", "iconText=", "iconVisibleInMenu=", "menu=", "menuRole=",
"priority=", "separator=", "shortcut=", "shortcutContext=", "shortcuts=",
"softKeyRole=", "statusTip=", "text=", "toolTip=", "visible=", "whatsThis=",
"shortcut", "shortcutContext", "shortcuts", "showStatusText", "softKeyRole",
"statusTip", "text", "toggle", "toolTip", "trigger", "whatsThis"]
def init_tray
    actions = []
    2.times do |i|
        actions[i] = ... # init and add to systray, store reference in array
    end
    update = Proc.new do |i|
        actions[i].setText('...') # update the text on one of the actions defined above
    end
    listener = ... # create a listener that can be called by Manager on certain events - will call the update Proc among other things.
    manager = Manager.new(..., listener)
end