使用拖动 wxFileDropTarget 时出现分段错误的原因

发布于 2024-11-29 19:41:48 字数 3048 浏览 3 评论 0原文

我尝试进行简单的拖放(将文件拖到文本区域)。我通过两种方式实现了拖放。让我们将它们标记为 V1V2

在这两个版本中,拖放功能都可以正常工作,但在 V1 中,当我尝试退出应用程序时,会出现分段错误。

问题:

也许有人可以启发我为什么使用 V1 会出现分段错误,而使用 V2 则不会出现分段错误? (我使用V2没有真正的问题,只是想知道发生分段错误的原因)

版本的简短描述:

  • V1 - 有一个名为Notepad的类。它继承于wxFramewxFileDropTarget,并封装wxTextCtrl并实现OnDropFiles(
  • V2 - class Notepad< /code> 仅从 wxFrame 继承并封装 wxTextCtrl,Drang'n'drop 由名为的单独类完成。 DRPTARGET,继承于wxFileDropTarget,并实现了OnDropFiles(

代码说明

(这里删掉了很多代码,不是我希望我没有删掉太多)

V1

    #include <wx/wx.h>
    #include <wx/dir.h>
    #include <wx/dnd.h>

    class Notepad : public wxFrame , public wxFileDropTarget {
        public:
            Notepad();
        private:
            wxTextCtrl* text_area;
            bool OnDropFiles(wxCoord x, wxCoord y, const wxArrayString &filenames);
    };

    bool Notepad::OnDropFiles (wxCoord WXUNUSED(x), wxCoord WXUNUSED(y), const wxArrayString &filenames){
        return this->text_area->LoadFile(filenames[0]);
    }

    Notepad::Notepad() : wxFrame(NULL, wxID_ANY, wxT("V1"), wxDefaultPosition, wxSize(650,500)) {
        wxBoxSizer *sizerh = new wxBoxSizer(wxHORIZONTAL);
        this->text_area = new wxTextCtrl(this, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER | wxTE_MULTILINE);
        sizerh->Add(this->text_area,1,wxEXPAND,0);
        this->SetSizer(sizerh);

        this->text_area->SetDropTarget(this);
    }



V2

    #include <wx/wx.h>
    #include <wx/dir.h>
    #include <wx/dnd.h>


    class DRPTARGET : public wxFileDropTarget{
        private:
        wxTextCtrl* text_area;

        bool OnDropFiles(wxCoord x, wxCoord y, const wxArrayString &filenames)
        {
            return this->text_area->LoadFile(filenames[0]);
        };

        public:
        DRPTARGET(wxTextCtrl* text_area)
        {
            this->text_area = text_area;
        };
    };



    class Notepad : public wxFrame , public wxFileDropTarget {
        public:
        Notepad(); // our default constructor


        private:
        wxTextCtrl* text_area;
    };


    Notepad::Notepad() : wxFrame(NULL, wxID_ANY, wxT("V2"), wxDefaultPosition, wxSize(650,500)) {
        wxBoxSizer *sizerh = new wxBoxSizer(wxHORIZONTAL);
        this->text_area = new wxTextCtrl(this, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER | wxTE_MULTILINE);
        sizerh->Add(this->text_area,1,wxEXPAND,0);
        this->SetSizer(sizerh);

        DRPTARGET* drop_target = new DRPTARGET(this->text_area);
        this->text_area->SetDropTarget(drop_target);

    }

I try to do simple drag'n'drop (drag file to text area). I implemented drag'n'drop in 2 ways. Lets mark them V1 and V2.

In both versions drag'n'drop works OK, but in V1 I get segmentation fault when I try to exit the application.

Question:

Maybe somebody could enlighten me why with V1 I get segmentation faul, while no segmentation fault with V2 ?
(I have no real problem using V2, just want to know the reason why segmenation fault occurs)

Short descriptions of the versions:

  • V1 - There is one class named Notepad. It inherits from wxFrame and wxFileDropTarget, and encapsulates wxTextCtrl and implements OnDropFiles(
  • V2 - class Notepad ingerits only from wxFrame and encapsulates wxTextCtrl. Drang'n'drop is done by separate class called DRPTARGET, which inherits from wxFileDropTarget and implements OnDropFiles(

Code for ilustration

(I cut out a lot of code here, which was not relevant. I hope I did not cut out too much)

V1:

    #include <wx/wx.h>
    #include <wx/dir.h>
    #include <wx/dnd.h>

    class Notepad : public wxFrame , public wxFileDropTarget {
        public:
            Notepad();
        private:
            wxTextCtrl* text_area;
            bool OnDropFiles(wxCoord x, wxCoord y, const wxArrayString &filenames);
    };

    bool Notepad::OnDropFiles (wxCoord WXUNUSED(x), wxCoord WXUNUSED(y), const wxArrayString &filenames){
        return this->text_area->LoadFile(filenames[0]);
    }

    Notepad::Notepad() : wxFrame(NULL, wxID_ANY, wxT("V1"), wxDefaultPosition, wxSize(650,500)) {
        wxBoxSizer *sizerh = new wxBoxSizer(wxHORIZONTAL);
        this->text_area = new wxTextCtrl(this, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER | wxTE_MULTILINE);
        sizerh->Add(this->text_area,1,wxEXPAND,0);
        this->SetSizer(sizerh);

        this->text_area->SetDropTarget(this);
    }

V2:

    #include <wx/wx.h>
    #include <wx/dir.h>
    #include <wx/dnd.h>


    class DRPTARGET : public wxFileDropTarget{
        private:
        wxTextCtrl* text_area;

        bool OnDropFiles(wxCoord x, wxCoord y, const wxArrayString &filenames)
        {
            return this->text_area->LoadFile(filenames[0]);
        };

        public:
        DRPTARGET(wxTextCtrl* text_area)
        {
            this->text_area = text_area;
        };
    };



    class Notepad : public wxFrame , public wxFileDropTarget {
        public:
        Notepad(); // our default constructor


        private:
        wxTextCtrl* text_area;
    };


    Notepad::Notepad() : wxFrame(NULL, wxID_ANY, wxT("V2"), wxDefaultPosition, wxSize(650,500)) {
        wxBoxSizer *sizerh = new wxBoxSizer(wxHORIZONTAL);
        this->text_area = new wxTextCtrl(this, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER | wxTE_MULTILINE);
        sizerh->Add(this->text_area,1,wxEXPAND,0);
        this->SetSizer(sizerh);

        DRPTARGET* drop_target = new DRPTARGET(this->text_area);
        this->text_area->SetDropTarget(drop_target);

    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

猫九 2024-12-06 19:41:48

当注册了放置目标时,wxWidgets 会很好地在退出主循环后删除指针。问题与文件放置目标对象的范围有关。

V1

this->text_area->SetDropTarget(this);

在这个版本中,“this”指的是框架。请记住,窗口指针也是由 wxWidgets 管理的;帧指针在文件放置目标之前被删除。当wxWidgets尝试删除放置目标指针时,它将尝试删除已经被删除的指针。

V2

DRPTARGET* drop_target = new DRPTARGET(this->text_area);
this->text_area->SetDropTarget(drop_target);

这种情况下,指针分配在堆中;但从未删除。在这种情况下,当 wxWidgets 尝试删除它时,它可以安全地执行此操作。

When a drop target is registered, wxWidgets will be nice and delete the pointer after the it exits the main loop. The problem has to do with the scope of the file drop target object.

V1

this->text_area->SetDropTarget(this);

In this version, "this" refers to the frame. Remember that the window pointers are also managed by wxWidgets; the frame pointer is deleted before the file drop target. When wxWidgets tries to delete the drop target pointer it will attempt to delete a pointer that has already been deleted.

V2

DRPTARGET* drop_target = new DRPTARGET(this->text_area);
this->text_area->SetDropTarget(drop_target);

In this case, the pointer is allocated in the heap; but never deleted. In this case, when wxWidgets attempts to delete it it can do so safely.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文