Ошибка при использовании wxSharedPtr

Это русская секция форума wxWidjets. В этой секции вы можете обсуждать любые вопросы, связанные с wxWidgets на вашем родном языке.
Post Reply
User avatar
Oleg
Earned a small fee
Earned a small fee
Posts: 23
Joined: Wed May 25, 2016 8:07 pm
Location: Ukraine

Ошибка при использовании wxSharedPtr

Post by Oleg » Wed May 25, 2016 8:41 pm

В программе использую wxSharedPtr<T> и wxWindowPtr<T> чтобы обернуть мемберы классов для безопасного удаления но вовремя закрытия окна wxFrame получаю вот такую ошибку:
errorwx.png
errorwx.png (31.54 KiB) Viewed 1635 times
Если пробовать дебажить во время выполнения строки:

Code: Select all

void DownloadFrame::OnCloseWindow(wxCloseEvent& WXUNUSED(e))
{
	Destroy();
}
Падает вот такой ексепшин:
errorwx1.png
errorwx1.png (25.12 KiB) Viewed 1635 times
Код моей программы:

ProjectApp.h

Code: Select all

#pragma once

//! Forward declaration.
class DownloadFrame;

class ProjectApp : public wxApp
{
	// Construction and destruction.
public:
	//! Constructor.
	ProjectApp();
	//! destructor.
	~ProjectApp();

	// Public interface.
public:
	//! Initializes the application.
	virtual bool OnInit(void);

	// Private data members.
private:
	wxWindowPtr<DownloadFrame> downloader_;
ProjectApp.cpp

Code: Select all

#include "pch.h"
#include "ProjectApp.h"
#include "DownloadFrame.h"

//! Macro will allow wxWidgets to create the application object during program execution.
IMPLEMENT_APP(ProjectApp)

//! Constructor.
ProjectApp::ProjectApp()
{ }

ProjectApp::~ProjectApp()
{ }

bool ProjectApp::OnInit(void)
{
	if (!wxApp::OnInit())
		return false;

	downloader_.reset(new DownloadFrame());
	downloader_->Show(true);

	return true;
}
DownloadFrame.h

Code: Select all

#pragma once

class DownloadFrame : public wxFrame
{
	// Construction and destruction.
public:
	//! Constructor.
	DownloadFrame();
	//! Destructor.
	~DownloadFrame();

	// Private interface.
private:
	//! On close event handler.
	void OnCloseWindow(wxCloseEvent& WXUNUSED(e));
	//! On cancel event handler.
	void OnCancel(wxCommandEvent& WXUNUSED(e));
	// Any class wishing to process wxWidgets events must use this macro.
	wxDECLARE_EVENT_TABLE();

	//
	// Private data members.
	//
private:
	//! Download button.
	wxWindowPtr<wxButton> downloadBtn_;
	//! Button sizer.
	wxSharedPtr<wxBoxSizer> btnSizer_;
	//! Top sizer.
	wxSharedPtr<wxBoxSizer> topSizer_;
};
DownloadFrame.cpp

Code: Select all

#include "pch.h"
#include "DownloadFrame.h"

//! Event table.
BEGIN_EVENT_TABLE(DownloadFrame, wxFrame)
	EVT_CLOSE(DownloadFrame::OnCloseWindow)
END_EVENT_TABLE()

DownloadFrame::DownloadFrame()
	: wxFrame(NULL, wxID_ANY, wxT("Downloader"))
{
	topSizer_.reset(new wxBoxSizer(wxHORIZONTAL));

 	//! Creates button.
	btnSizer_.reset(new wxBoxSizer(wxVERTICAL));
	downloadBtn_.reset(new wxButton(this, wxID_ANY, wxT("Cancel"), wxDefaultPosition, wxSize(100, 30)));
	downloadBtn_->Bind(wxEVT_BUTTON, &DownloadFrame::OnCancel, this);
	
	btnSizer_->Add(downloadBtn_.get(), wxSizerFlags().Proportion(0).Border(wxALL, 10).Right());
	topSizer_->Add(btnSizer_.get(), wxSizerFlags().Proportion(1).Center());

}

void DownloadFrame::OnCancel(wxCommandEvent& WXUNUSED(e))
{
	wxMessageBox(wxT("Downloading has been canceled"), wxT("Download"), wxOK, this, wxDefaultCoord, wxDefaultCoord);
}

void DownloadFrame::OnCloseWindow(wxCloseEvent& WXUNUSED(e))
{
	Destroy();
}
Несовсем понятно почему так происходит, может я неправильно использую:
class wxSharedPtr< T > http://docs.wxwidgets.org/trunk/classwx ... _01_4.html
или
class wxWindowPtr< T > http://docs.wxwidgets.org/trunk/classwx ... _01_4.html

Спасибо.

User avatar
doublemax
Moderator
Moderator
Posts: 13990
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Ошибка при использовании wxSharedPtr

Post by doublemax » Wed May 25, 2016 9:12 pm

It doesn't make sense to use shared pointers for any of those objects, because they all will be deleted by their parent anyway.
Use the source, Luke!

User avatar
Oleg
Earned a small fee
Earned a small fee
Posts: 23
Joined: Wed May 25, 2016 8:07 pm
Location: Ukraine

Re: Ошибка при использовании wxSharedPtr

Post by Oleg » Wed May 25, 2016 9:19 pm

Этот код не вызовет утечки при инициализации его мемберов в конструкторе класса??? :shock:

Code: Select all

class DownloadFrame : public wxFrame
{
	//...

	//
	// Private data members.
	//
private:
	//! Download button.
	wxBoxSizer* btnSizer_;
	wxButton* downloadBtn_;
	wxBoxSizer* topSizer_;
};

DownloadFrame::DownloadFrame()
	: wxFrame(NULL, wxID_ANY, wxT("Downloader"), wxDefaultPosition)
	, btnSizer_(new wxBoxSizer(wxVERTICAL))
	, downloadBtn_(new wxButton(this, wxID_ANY, wxT("Cancel"), wxDefaultPosition, wxSize(100, 30)))
	, topSizer_(new wxBoxSizer(wxHORIZONTAL))
{  }
Где же тогда будет освобождена память?

User avatar
doublemax
Moderator
Moderator
Posts: 13990
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Ошибка при использовании wxSharedPtr

Post by doublemax » Wed May 25, 2016 10:05 pm

These objects will all be recursively destroyed when the wxFrame gets destroyed.

http://docs.wxwidgets.org/trunk/overvie ... etion.html
Use the source, Luke!

User avatar
Oleg
Earned a small fee
Earned a small fee
Posts: 23
Joined: Wed May 25, 2016 8:07 pm
Location: Ukraine

Re: Ошибка при использовании wxSharedPtr

Post by Oleg » Wed May 25, 2016 10:23 pm

Ok. It is clear.

Аccording with this documentation:
https://wiki.wxwidgets.org/Avoiding_Mem ... al_windows
We need not to use smart pointers with class that is derived off wxWindow :!:
When a wxWindow is destroyed, it automatically deletes all its children. These children are all the objects that received the window as the parent-argument in their constructors.
I have one question:
Should i use wxSharedPtr with wxSize-s? It does not receive the window as the parent-argument in his constructor.

User avatar
doublemax
Moderator
Moderator
Posts: 13990
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Ошибка при использовании wxSharedPtr

Post by doublemax » Wed May 25, 2016 11:20 pm

Should i use wxSharedPtr with wxSizer-s?
No.
It does not receive the window as the parent-argument in his constructor.
That's true, but with wxWindow::SetSizer() the window takes ownership of the sizer and will delete it. And all sizers that are embedded in other sizers will be deleted by their "parent" sizers.

Under normal circumstances you never have to delete a wxSizer yourself.
Use the source, Luke!

User avatar
Oleg
Earned a small fee
Earned a small fee
Posts: 23
Joined: Wed May 25, 2016 8:07 pm
Location: Ukraine

Re: Ошибка при использовании wxSharedPtr

Post by Oleg » Thu May 26, 2016 8:24 am

Got it. Thanks a lot!

Post Reply