如何在破坏父窗口之前关闭此GTK :: Messagedialog?
我目前正在尝试创建一个简单的GTKMM程序,该程序的按钮可以产生对话框。但是,我目前遇到问题,作为AppWindow类的破坏者,导致关闭对话框的Segfault。我检查unique_ptr
是否是nullptr
在呼叫关闭之前,但是如果对话框在主窗口之前已经关闭,则它将崩溃。我在这里采取正确的方法吗? unique_ptr
在调用破坏者之前被释放吗?
main.c
#include "AppWindow.hpp"
#include <cstdio>
#include <cstdlib>
#include <gtkmm/application.h>
int main(int argc, char **argv) {
std::shared_ptr<Gtk::Application> app = Gtk::Application::create("org.dylanweber.test");
return app->make_window_and_run<AppWindow>(argc, argv);
}
appwindow.hpp
#include <gtkmm/button.h>
#include <gtkmm/messagedialog.h>
#include <gtkmm/window.h>
#include <iostream>
#pragma once
class AppWindow : public Gtk::Window {
public:
AppWindow();
virtual ~AppWindow();
private:
Gtk::Button m_button;
std::unique_ptr<Gtk::MessageDialog> dialog;
void on_button_clicked();
};
appwindow.cpp
#include "AppWindow.hpp"
AppWindow::AppWindow() : m_button("Hello, world!") {
this->m_button.set_margin(10);
this->m_button.signal_clicked().connect(sigc::mem_fun(*this, &AppWindow::on_button_clicked));
this->set_child(this->m_button);
}
AppWindow::~AppWindow() {
if (this->dialog != nullptr) {
this->dialog->close(); // seg fault here
}
}
void AppWindow::on_button_clicked() {
this->dialog = std::make_unique<Gtk::MessageDialog>(
"Button clicked", false, Gtk::MessageType::QUESTION, Gtk::ButtonsType::OK);
this->dialog->set_transient_for(*this);
this->dialog->set_secondary_text("Hello");
this->dialog->set_default_response(Gtk::ResponseType::OK);
this->dialog->show();
}
I'm currently trying to create a simple Gtkmm program that has a button which spawns a dialog box. I'm currently having issues, however, as the destructor for the AppWindow class causes a segfault closing the dialog box. I check if the unique_ptr
is nullptr
before calling close, but even with that check it will crash if the dialog has already been closed before the main window has. Am I taking the correct approach here? Is the unique_ptr
getting freed before the destructor is called?
main.c
#include "AppWindow.hpp"
#include <cstdio>
#include <cstdlib>
#include <gtkmm/application.h>
int main(int argc, char **argv) {
std::shared_ptr<Gtk::Application> app = Gtk::Application::create("org.dylanweber.test");
return app->make_window_and_run<AppWindow>(argc, argv);
}
AppWindow.hpp
#include <gtkmm/button.h>
#include <gtkmm/messagedialog.h>
#include <gtkmm/window.h>
#include <iostream>
#pragma once
class AppWindow : public Gtk::Window {
public:
AppWindow();
virtual ~AppWindow();
private:
Gtk::Button m_button;
std::unique_ptr<Gtk::MessageDialog> dialog;
void on_button_clicked();
};
AppWindow.cpp
#include "AppWindow.hpp"
AppWindow::AppWindow() : m_button("Hello, world!") {
this->m_button.set_margin(10);
this->m_button.signal_clicked().connect(sigc::mem_fun(*this, &AppWindow::on_button_clicked));
this->set_child(this->m_button);
}
AppWindow::~AppWindow() {
if (this->dialog != nullptr) {
this->dialog->close(); // seg fault here
}
}
void AppWindow::on_button_clicked() {
this->dialog = std::make_unique<Gtk::MessageDialog>(
"Button clicked", false, Gtk::MessageType::QUESTION, Gtk::ButtonsType::OK);
this->dialog->set_transient_for(*this);
this->dialog->set_secondary_text("Hello");
this->dialog->set_default_response(Gtk::ResponseType::OK);
this->dialog->show();
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
评论中的建议是正确的,您应该将驱动器空白,而不是呼叫
对话 - &gt; close()
。要查看为什么,请注意,此函数是GTK C API函数的包装器gtk_window_close
,以gtk :: window> window class class
(从哪个gtk :: :: :: :: witch)定义。 Messagedialog
通过gtk :: Dialog
):):gobj()
返回内部gobject _
pointer(Objectbase Base <定义/code> class)指向C API的GTK句柄,当前类无需。该指针在
gtk_window_close
中使用:正如vs debugger在运行示例时所说的那样,segfault发生了,因为
widget
是_gtk_widget_get_get_realized
中的0。关闭对话框时已清除,因为默认情况下(通过CLOSE
方法或关闭按钮)窗口意味着销毁它,因为您可以通过调用gtk_window_destroy
来查看。内部gtk_window_close
。使用GTK的C APIGTK_WINDOW_DESTROY
通过相当复杂的回调机制函数销毁此功能,可以适当地注册与内存管理有关的C ++功能。数据断点帮助精确地指出了gobject _
将设置为0 -object :: destrion_notify _
(该本身是从GTK的参考计数代码中间接调用的,因为对话对话的参考计数降至0) :因此,关闭对话框后,
Messagedialog
的内部句柄将被清除为0(顺便说一句,Messagedialog Destructor在此期间未调用,我也在调试器中检查了),并且由于您将其称为<代码>关闭假定不是,您会得到内存访问问题。如果gobject _
已经清除了destructor,请正确工作,因此在关闭on_button_clicked
关闭后,您不会在重新创建Messagedialog
中遇到问题代码> std :: simelo_ptr 如果存在的话,请调用上一个对象的destructor),以及在gobject _
的情况下仍然指向有效对象,因此即使它也不应遇到问题对话在娱乐前没有关闭。出于相同的原因,Messagedialog
在AppWindow中调用
destructor在窗口前是否关闭对话框的destructor destructor。PS请注意,GTKMM
.cc
文件来自VCPKG buildetre,使用GTKMM的自定义预处理生成gmmproc
gmmproc 工具在构建过程中,来自cccg
source>源文件,因此您不会在存储库中找到它们。Suggestion in the comments is right, you should leave your destructor empty and not call
dialog->close()
there. To see why, note that this function is a wrapper for GTK C API functiongtk_window_close
, defined like this forGtk::Window class
(from whichGtk::MessageDialog
inherits throughGtk::Dialog
):Here
gobj()
returns internalgobject_
pointer (defined inObjectBase
class) pointing to C API's GTK handle, which current class incapsulates. This pointer is used insidegtk_window_close
this way:As VS debugger told when running your example, segfault happens because
widget
is 0 in_gtk_widget_get_realized
. It was cleared when dialog was closed, because by default closing (throughclose
method or close button) a window means destroying it, as you can see e.g. by a call togtk_window_destroy
insidegtk_window_close
. This destroy using GTK's C APIgtk_window_destroy
function through a pretty complex callback mechanism reaches appropriately registered C++ functions relating to memory management. Data breakpoint helped pinpoint exactly wheregobject_
was set to 0 -Object::destroy_notify_
(which itself was indirectly called from reference counting code of GTK because dialog's reference count dropped to 0):So, after closing a dialog,
MessageDialog
's internal handle is cleared to 0 (BTW, MessageDialog destructor is not called during this, which I also checked in a debugger), and since you call aclose
function which assumes it isn't, you get memory access problems. Destructor correctly works in casegobject_
was already cleared, so you don't get problems with recreatingMessageDialog
inon_button_clicked
after it was closed (wherestd::unique_ptr
calls destructor for previous object if it's present), as well as in casegobject_
still points to valid object, so you shouldn't have problems with it even if dialog wasn't closed before recreation. For the same reasons,MessageDialog
destructor called inAppWindow
destructor is OK regardless of whether the dialog was closed before the window.P.S. Note that the gtkmm
.cc
files here are from vcpkg buildtrees, generated using gtkmm's custom preprocessinggmmproc
tool during build process from.ccg
source files, so you won't find them in repositories.