2016-11-20 103 views
0

我的GUI应用程序有2个窗口。 主窗口销毁信号设置为使用gtk_main_quit退出应用程序。旧窗口的信号处理程序被新的窗口信号处理程序取代GTK +

其他窗口销毁信号设置为使用方法gtk_widget_destroy销毁该特定窗口。

从主窗口我们启动其他窗口。点击关闭button(X)后启动另一个窗口后,另一个窗口成功销毁,但主窗口继续运行,到目前为止都很好。

现在,当我们点击主窗口关闭button(X)它没有退出整个应用程序,而是它破坏了主窗口并且进程继续运行。

如果我不从主窗口启动其他窗口,那么一切正常,应用程序成功退出。

这里是一个再现这一问题的示例代码:

#include <gtk/gtk.h> 

#include <iostream> 

using namespace std; 

class OtherWindow { 
    private: 
     int number; 

     GtkWidget* window; 

     GtkWidget* button; 

    public: 
     OtherWindow(int num); 

     static void read_number(GtkWidget *widget, gpointer data); 

}; 

OtherWindow::OtherWindow(int num) 
{ 
    number = num; 
    window = gtk_window_new(GTK_WINDOW_TOPLEVEL); 

    button = gtk_button_new_with_label("Read Number"); 

    gtk_container_add(GTK_CONTAINER(window), button); 

    // signal handler 
    g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_widget_destroy), NULL); 

    g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(OtherWindow::read_number), this); 

    gtk_widget_show_all(window); 

    gtk_main(); 

} 

void OtherWindow::read_number(GtkWidget *widget, gpointer data) 
{ 
    OtherWindow* other_win = static_cast<OtherWindow*>(data); 
    cout << other_win->number << endl; 
} 

class MainWindow { 

    private: 
     GtkWidget* window; 

     GtkWidget* button; 

    public: 
     MainWindow(); 

     static void open_other_window(GtkWidget *widget, gpointer data); 
}; 


MainWindow::MainWindow() 
{ 
    window = gtk_window_new(GTK_WINDOW_TOPLEVEL); 

    button = gtk_button_new_with_label("Open Another Window"); 

    gtk_container_add(GTK_CONTAINER(window), button); 

    // signal handler 
    g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL); 

    g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(MainWindow::open_other_window), NULL); 

    gtk_widget_show_all(window); 

    gtk_main();  
} 

void MainWindow::open_other_window(GtkWidget *widget, gpointer data) 
{ 
    OtherWindow other(10); 
} 

int main(int argc, char* argv[]) 
{ 
    gtk_init(&argc,&argv); 

    MainWindow win; 

} 

还有一个疑问是,当我试图从OtherWindow构造函数中删除gtk_main环路,则申请成功退出,但如果我从OtherWindow构造函数删除gtk_main循环,然后单击其他窗口上的按钮以使用指针引用访问成员变量,然后我的应用程序出现分段错误。

另外我没有使用gtkmm,因为我没有什么限制,因为我必须在没有编译器支持的旧Solaris服务器上运行应用程序。

从主窗口启动其他窗口是非常普遍的事情,我想我缺少一些基本的东西。任何可以帮助这里的东西。

+0

为什么你运行多个mainloops? – jku

+0

我们不必为每个顶层窗口运行主循环。 无论如何,如果你不运行OtherWindow主循环,它会转储核心(分段错误),正如我在文章中提到的那样。 它转储核心的原因是因为一旦OtherWindow被实例化,它会立即被删除,因为在它们之间没有阻塞函数,并且在稍后的信号处理程序中,我们尝试使用对象引用,因为对象已被释放。 – mSatyam

+0

早些时候我确实只使用了一个主循环,但是因为我正在写这个注释而被抛弃了,所以我非常肯定我找到了解决方案。对于某些问题,当我提出一个问题时,只有我的思维才起作用,现在看到我发现什么地方出了问题。让我试着回头确认一下。 感谢让我的大脑足够努力。 – mSatyam

回答

0

还有一个问题可以回答我自己。 这里首先要注意的是为什么我使用@jku指出的两个主循环。 我使用了两个主循环,因为之前只有一个循环,我的进程正在倾卸核心,而我并没有集中检查哪里出了问题,而是开始以其他方式思考并插入一个不需要的主循环。

现在为什么它是倾销核心刚刚击中我的脑海,因为我在我的帖子上写评论。这是被释放的对象,其引用我仍在使用OtherWindow的Button的信号处理程序。 当我在堆栈上创建对象时,一旦函数结束,对象被删除,但后来在信号处理程序中,当我尝试使用它时,它肯定会转储我刚刚知道的核心。

因此,我通过引入一个主循环来处理seg fault的方式是一个非常糟糕的主意,因为我们应该只使用一个主循环,因为引入更多主循环会导致进一步的其他问题,如后面所述。

因此,只有在上面的代码一些变化使得一切权利:

首先要从OtherWindow构造GTK的主循环。

其次动态创建OtherWindow对象如下:

void MainWindow::open_other_window(GtkWidget *widget, gpointer data) 
{ 
    OtherWindow* other = new OtherWindow(10); 
}