我想将自己的gtk程序从旧的MinGW移到最新的。我在过去的两周内遇到了很多问题,但找不到办法。请参考我发布的其他2个问题:
does mingw influence compilation a gtk program和compile gtk in mingw but failed。
最后,我在gtk+2.24.10
编辑了MinGW
。其次是环境细节:
GTK version gcc version
old mingw 2.10.11 -- from third party 3.4.5
new mingw 2.24.10 -- compiled by myself 4.7.2 or 4.6.2 -- I tried both
对于旧环境中的程序,一切运行良好。
对于新环境中的程序,上面提到的问题“确实影响编译gtk程序”消失了。但是有一个新问题我无法找到任何线索:
启动程序时,如果我移动GUI窗口,它就会崩溃。我使用gdb进行调试,但是如果它崩溃了,系统就会被冻结。唯一的方法是使用“ctrl + alt + del”激活任务管理器并停止程序。然后在GDB中,where
或bt full
未显示任何有用信息。如果我不移动GUI窗口,窗口中的所有功能都运行良好。还有一件事,我的程序使用来自第三方的openssl
和pdflib
。该程序链接到libs,但只在启动GUI窗口时不使用它们。
我自己的代码中有错误吗?我不这么认为,因为它在旧的MinGW环境中运行良好。有关g_thread_create, g_thread_init is deprecated
的一些警告在gtk + 2.24.10包中,但不会显示在gtk + 2.10.11包中。
gtk系统有什么问题,包括我自己在MinGW编译的gtk,glib,cario,atk等?我说不出来。但是gtk包中包含的gtk_demo
运行良好,我可以将程序的窗口移动到任何地方。
它与gcc版本有关吗?我说不出来。我用谷歌搜索,发现有人抱怨他的gtk程序符合gcc 4.7.x不稳定,并受到许多突然崩溃的影响。 gcc 4.6.2绝对是有人建议的。但在我的情况下,它仍然崩溃,甚至由gcc 4.6.2编译。
由于ABI问题,它与来自第三方的openssl和pdflib有关吗?我不知道。
M代码在Linux环境中编译--gtk + 2.24.6。它确实运行良好。
更新1 :
我发现了一些线索。问题来自thread
。但我仍然不知道为什么它在旧的MinGW中起作用但在新的MinGW中失败了。接下来是一个简单的例子。
正如我所说,如果我在旧的MinGW中编译它,它可以工作 - 数据,实际上是一个计数器,在小部件中更新。我可以移动窗户。
如果我在新的MinGW中编译它,它可以工作 - 数据,实际上是一个计数器,在小部件中更新。但如果我移动窗户,它会崩溃。如果我评论了与线程相关的内容,那么我可以移动窗口,但不会在窗口中更新数据。
#include <gtk/gtk.h>
static int counter = 0;
static PangoLayout* layout;
static GdkGC* gc1;
static GdkGC* gc2;
//**/static GMutex* mu;
static gboolean on_expose_event(GtkWidget* widget, GdkEventExpose* event)
{
gchar the_string[20];
//**/g_mutex_lock(mu);
gdk_draw_rectangle(GDK_DRAWABLE(widget->window), gc1, TRUE, 0, 0, widget->allocation.width, widget->allocation.height);
snprintf(the_string, 20, "%d", counter);
pango_layout_set_text(layout, the_string, -1);
gdk_draw_layout(GDK_DRAWABLE(widget->window), gc2, 180, 120, layout);
//**/g_mutex_unlock(mu);
g_print (".");
return FALSE;
}
gpointer func(gpointer data)
{
//**/g_usleep(10000);
GdkWindow* window = GDK_WINDOW(data);
while(TRUE)
{
gdk_threads_enter();
gdk_window_invalidate_rect(window, NULL, FALSE);
gdk_threads_leave();
//**/gdk_window_process_updates(window, FALSE);
if(counter % 100 == 0) g_print("X");
g_usleep(10);
++counter;
}
return FALSE;
}
int main(int argc, char** argv)
{
GtkWidget* window;
GtkWidget* drawer;
GdkColormap* colormap;
GdkColor color;
g_thread_init(NULL);
gdk_threads_init();
gtk_init(&argc, &argv);
//:Create widgets and
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
drawer = gtk_drawing_area_new();
gtk_widget_set_size_request(drawer, 400, 300);
gtk_container_add(GTK_CONTAINER(window), drawer);
//.
gtk_widget_show_all(window);
//:Initializing Graphic Contexts
colormap = gtk_widget_get_colormap(GTK_WIDGET(drawer));
layout = gtk_widget_create_pango_layout(GTK_WIDGET(drawer), NULL);
gc1 = gdk_gc_new(GDK_DRAWABLE(GTK_WIDGET(drawer)->window));
gc2 = gdk_gc_new(GDK_DRAWABLE(GTK_WIDGET(drawer)->window));
gdk_color_parse("#000", &color);
gdk_colormap_alloc_color(colormap, &color, FALSE, TRUE);
gdk_gc_set_background(gc1, &color);
gdk_color_parse("#fff", &color);
gdk_colormap_alloc_color(colormap, &color, FALSE, TRUE);
gdk_gc_set_foreground(gc2, &color);
//.
g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
g_signal_connect(G_OBJECT(drawer), "expose_event", G_CALLBACK(on_expose_event), NULL);
//**/mu = g_mutex_new();
//Run the problematic thread!
g_thread_create(func, GTK_WIDGET(drawer)->window, FALSE, NULL);
gdk_threads_enter();
gtk_main();
gdk_threads_leave();
//**/g_mutex_free(mu);
return 0;
}
编译:
gcc -g -o example update_widget.c `pkg-config --libs --cflags gtk+-2.0 gthread-2.0`
更新2 :
我查看config.log
汇编glib
,找到了以下字词:
configure:26678: WARNING: I can't find the MACRO to enable thread safety on your
platform (normally it's _REENTRANT). I'll not use any flag on
compilation now, but then your programs might not work.
Please provide information on how it is done on your system.
它是否影响线程功能?
我对glib
编译的配置是:
export CFLAGS="-march=i686"
./configure --prefix=$HOME/gtk+$GTK_VERSION --with-threads=win32 --with-pcre=internal
make
make install