Haskell 为什么这个最小的Gtk2Hs程序会泄漏内存

Haskell 为什么这个最小的Gtk2Hs程序会泄漏内存,haskell,gtk,gtk2hs,Haskell,Gtk,Gtk2hs,在Win32和Win32 64上使用GHC 7.4.2和GtkHs 0.12.4,此程序占用越来越多的内存,在我的机器上消耗大约2Mb/秒。 我只是想用Gtk制作一个动画(这就是为什么我要使窗口失效,以便立即重新绘制) 我试图用RTS选项分析内存使用情况,但该内存不可见 发生了什么事 import Graphics.UI.Gtk main :: IO () main = do initGUI window <- windowNew onDestroy window

在Win32和Win32 64上使用GHC 7.4.2和GtkHs 0.12.4,此程序占用越来越多的内存,在我的机器上消耗大约2Mb/秒。 我只是想用Gtk制作一个动画(这就是为什么我要使窗口失效,以便立即重新绘制)

我试图用RTS选项分析内存使用情况,但该内存不可见

发生了什么事

import Graphics.UI.Gtk

main :: IO ()
main = do
    initGUI
    window <- windowNew
    onDestroy window mainQuit
    onExpose window (\_ -> widgetQueueDraw window >> return True)
    widgetShowAll window
    mainGUI
import Graphics.UI.Gtk
main::IO()
main=do
initGUI
窗口widgetQueueDraw窗口>>返回真值)
widgetShowAll窗口
美因圭
--编辑:我使用的是Gtk found的版本,正好是2.24.10


--Edit2:因此,使用外部计时器而不是从expose事件请求
widgetQueueDraw
,可以修复问题。现在可以了,但我不明白为什么。我已经在几种语言和几种GUI框架中使用了这种方法(在paint事件中使GUI控件无效)。通常,调用invalidate只会设置一个标志,该标志在下次GUI线程启动时被读取。它在GUI线程中结束,在每个帧中重新绘制控件,但这实际上是我在这里想要的。它看起来像一个循环,但在Gtk2Hs中。

我认为您的程序进入了一个循环。当窗口接收到曝光事件(即,请求它重新绘制自身)时,您不会进行任何绘制。相反,您强制它重新绘制自身,这反过来会发出一个暴露事件,依此类推。你必须把问题分成两部分。您应该设置一个计时器,该计时器调用一个函数来准备动画的下一步,并调用
widgetQueueDraw
将场景渲染到窗口上。实际渲染应作为对窗口暴露事件的反应。

对于GHC 7.6.2,在Fedora x86_64上使用GTKhs 0.12.4和GTK+1.2.10,使用-O2或无显式优化标志,我无法重现此错误。我确实看到,如果没有-O2,内存使用率会略高(但没有增长),CPU使用率也会非常高。有趣的是,我将尝试使用不同版本的GHC和GtkOh,我应该说我的GTK-2版本,而不是GTK+。GTK-2的版本是2.24.16。抱歉,我花了一些时间来尝试。它确实解决了问题,但我不明白为什么。我将更新原始问题。