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 fromwxFrameandwxFileDropTarget, and encapsulateswxTextCtrland implementsOnDropFiles( - V2 – class
Notepadingerits only fromwxFrameand encapsulateswxTextCtrl. Drang’n’drop is done by separate class calledDRPTARGET, which inherits fromwxFileDropTargetand implementsOnDropFiles(
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);
}
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
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
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.