Причина ошибки сегментации при использовании перетаскивания wxFileDropTarget - PullRequest
2 голосов
/ 15 августа 2011

Я пытаюсь сделать простой drag'n'drop (перетащить файл в текстовую область). Я реализовал drag'n'drop двумя способами. Давайте отметим их V1 и V2.

В обеих версиях drag'n'drop работает нормально, но в V1 при попытке выйти из приложения возникает ошибка сегментации.

Вопрос:

Может быть, кто-нибудь мог бы просветить меня, почему с V1 я получаю ошибку сегментации, в то время как нет ошибки сегментации с V2? (У меня нет реальной проблемы с использованием V2, просто хочу узнать причину возникновения ошибки сегментации)

Краткое описание версий:

  • V1 - существует один класс с именем Notepad. Он наследуется от wxFrame и wxFileDropTarget, инкапсулирует wxTextCtrl и реализует OnDropFiles(
  • V2 - класс Notepad содержит только от 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);

    }

1 Ответ

2 голосов
/ 17 августа 2011

Когда цель сброса зарегистрирована, wxWidgets будет хорош и удалит указатель после выхода из основного цикла. Проблема связана с областью действия целевого объекта удаления файла.

V1

this->text_area->SetDropTarget(this);

В этой версии «это» относится к кадру. Помните, что указателями окон также управляет wxWidgets; указатель кадра удаляется до цели удаления файла. Когда wxWidgets пытается удалить удаленный целевой указатель, он пытается удалить уже удаленный указатель.

V2

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

В этом случае указатель выделяется в куче; но никогда не удаляется. В этом случае, когда wxWidgets пытается удалить его, он может сделать это безопасно.

...