当启动和关闭wxHaskell GUI,然后再次启动另一个wxHaskell GUI时,应用程序会因堆栈溢出而产生分段错误。
简单示范资料来源:
module Main where
import Graphics.UI.WX
main = do
start $ frame []
start $ frame []这似乎是一个老错误,参见http://permalink.gmane.org/gmane.comp.lang.haskell.wxhaskell.general/789。这条消息链接到wxHaskell的SourceForge存储库中的一个问题,最近有一条评论提到了一个版本的wxHaskell(似乎是wxWidgets 2.9的开发分支),它没有错误。
我在wxWidgets 2.8中使用Ubuntu12.04,所以我必须使用wxHaskell 0.13。我试图通过查看可能正在工作的开发版本的变更量来查找有关此bug的任何信息,但什么也找不到。
这种错误行为可以修正为wxHaskell 0.13,或者至少有可能找到某种解决办法?重写应用程序来使用一个持久的GUI似乎没有必要复杂。
发布于 2013-10-23 15:40:50
可以为bug设计一个解决方案,至少对于wxWidget-2.8和GTK是这样的。
不幸的是,wxHaskell开发人员似乎没有将GUI作为一个可重入的界面来实现。在每个GUI上,wxHaskell以这样的方式调用wxWidgets,即从wxWidgets源文件src/gtk/app.cpp调用一个方法wxApp::Initialize。特别是,此方法执行以下两行来初始化wxWidgets的GTK事件循环:
wxgs_poll_func = g_main_context_get_poll_func(NULL);
g_main_context_set_poll_func(NULL, wxapp_poll_func);问题是,在第一次GUI启动时,wxgs_poll_func设置为GTK开头的任何轮询函数(似乎是g_poll),而在第二次GTK启动时,wxgs_poll_func设置为wxapp_poll_func --在第一次GUI启动时,我们将wxapp_poll_func设置为GTK轮询函数,当我们在使用g_main_context_get_poll_func的第二个GUI启动时请求它时,就会得到wxapp_poll_func。
在执行wxapp_poll_func时,这会适得其反,据我所知,在调用wxgs_poll_func初始化wxWidgets之前,应该调用GTK使用的任何轮询函数。在第一个GUI启动时,它实际上调用轮询函数GTK,而在第二个GUI启动时,它调用自己,进入无限递归并导致堆栈溢出。
比较麻烦的解决方法是在每个GUI会话之后手动将g_poll重置为GTK轮询函数。这可以使用以下C函数来实现:
#include <glib.h>
void reset_g_poll()
{
g_main_context_set_poll_func(NULL, g_poll);
}将其编译为共享库,并将其作为C外接函数导入,并进行适当修改的演示工作。修改后的演示:
module Main where
import Graphics.UI.WX
foreign import ccall unsafe "reset_g_poll"
reset_g_poll :: IO ()
main = do
start $ frame []
reset_g_poll
start $ frame []
reset_g_pollhttps://stackoverflow.com/questions/18969516
复制相似问题