Наследование от wxEvtHandler , уничтож Topic is solved

Это русская секция форума wxWidjets. В этой секции вы можете обсуждать любые вопросы, связанные с wxWidgets на вашем родном языке.
Post Reply
m1t0z
Knows some wx things
Knows some wx things
Posts: 25
Joined: Sat Aug 16, 2008 9:03 am

Наследование от wxEvtHandler , уничтож

Post by m1t0z »

Здравствуйте. Имеется необходимость создать класс, умеющий принимать сообщения( аля от wxPostEvent ). Самым логичным показалось унаследовать класс от wxEvtHandler. Таким образом последнее время и поступал, пока не начлася падёж на одном из таких классов. После продолжительных поисков причину нашел(кажется). Заключается она в том что при удалении объекта такого класса в очереди сообщений еще могут остаться к нему необработанные сообщения. Тоже самое, насколько я знаю, случается если удалять через delete объекты, унаследованные от wxWindow - посему в документации и рекомендуют настоятельно узать wxWindow::Destroy(), реализующий отложенное уничожение объекта.
Каким образом стоит поступать мне - перенаследовать все классы от wxWindow и узать Destroy или есть какой-то другой, способ( может отложенное удаление как то заложенно в сам класс wxEvtHandler ). Вариант с наследованием от wxWindow не очень симпатизирует - все таки не "окна" делаю.
radcapricorn
Experienced Solver
Experienced Solver
Posts: 70
Joined: Fri Nov 07, 2008 4:25 pm
Location: Saint-Petersburg, Russia

Post by radcapricorn »

в очереди сообщений еще могут остаться к нему необработанные сообщения.
Как это "к нему"? Падеж может быть, если например кто-то пытается вызвать метод по указателю на удаленный объект. Но при чем здесь очередь сообщений? Если я правильно понимаю, то это может возникать разве что из-за того, что объект был удален, но не изъят из списка обработчиков, в который он был помещен.

Можно пример использования такого класса для ясности?
win xp pro sp3/VS Express 2008/MinGW;
win Vista Ultimate/VS 2005;
Debian Lenny/gcc/cegcc-mingw32ce;
wxWidgets-2.8.9 w/wxWinCE;
m1t0z
Knows some wx things
Knows some wx things
Posts: 25
Joined: Sat Aug 16, 2008 9:03 am

Post by m1t0z »

radcapricorn wrote: Если я правильно понимаю, то это может возникать разве что из-за того, что объект был удален, но не изъят из списка обработчиков, в который он был помещен.
Вообщем то это я имел ввиду
radcapricorn wrote: Можно пример использования такого класса для ясности?
Частный пример, на котором падеж:

Есть класс, унаследованный от wxEvtHandler. В нем агрегирован объект типа wxSocketBase *. У данного объекта я использую метод SetEventHandler, для того, чтобы отслеживать события, происходящие на сокете. Параметром в SetEventHandler передаю this.

Дальше наибольший интерес представляет деструктор класса:
в котором я вызываю Destroy для объекта сокета( + предварительно вызываю notify(false) для того же объекта сокета).

Если я не вызываю деструктор класса( не уничтожаю объект ) проблем никаких нет, а вот когда вызываю - случаются падежи.

Т.е. действительно подозрения на то, что мой объект не был изьят из списков обработчиков. Как это можно сделать?
radcapricorn
Experienced Solver
Experienced Solver
Posts: 70
Joined: Fri Nov 07, 2008 4:25 pm
Location: Saint-Petersburg, Russia

Post by radcapricorn »

В случае с wxSocketBase - никак, да это и не нужно. Скорее всего нужно убедиться в том, что объект-агрегат умрет после сокета.

Здесь возможен вариант, что события, сгенерированные сокетом до его удаления по Destroy(), еще будут доставляться (т.к. он "физически" умрет только в слующий idle time). Только вот сам обработчик к этому времени будет уже уничтожен.

В данном случае это чисто мое ИМХО, я просто бегло пробежался по исходникам wxWidgets. Так что могу заблуждаться :wink:

Случай действительно интересный. Падежи происходят в деструкторе или "случайно", но после вызова деструктора?
win xp pro sp3/VS Express 2008/MinGW;
win Vista Ultimate/VS 2005;
Debian Lenny/gcc/cegcc-mingw32ce;
wxWidgets-2.8.9 w/wxWinCE;
m1t0z
Knows some wx things
Knows some wx things
Posts: 25
Joined: Sat Aug 16, 2008 9:03 am

Post by m1t0z »

radcapricorn wrote:Падежи происходят в деструкторе или "случайно", но после вызова деструктора?
В том то и дело, что случайно после вызова деструктора.
m1t0z
Knows some wx things
Knows some wx things
Posts: 25
Joined: Sat Aug 16, 2008 9:03 am

Post by m1t0z »

radcapricorn wrote:В случае с wxSocketBase - никак, да это и не нужно. Скорее всего нужно убедиться в том, что объект-агрегат умрет после сокета.
Есть идеи как это реализовать, без наследования от wxSocketClient/wxSocketServer?
radcapricorn
Experienced Solver
Experienced Solver
Posts: 70
Joined: Fri Nov 07, 2008 4:25 pm
Location: Saint-Petersburg, Russia

Post by radcapricorn »

Судя по всему, так и есть - остается какая-то связка между сокетом и обработчиком, причем второй удаляется явно раньше первого.

Можно попробовать реализовать Destroy() для обработчика вот так:

Code: Select all

wxAppTraits *traits = wxTheApp ? wxTheApp->GetTraits() : 0;
if (traits)
{
    traits->ScheduleForDestroy(this);
}
else
{
    delete this;
}
win xp pro sp3/VS Express 2008/MinGW;
win Vista Ultimate/VS 2005;
Debian Lenny/gcc/cegcc-mingw32ce;
wxWidgets-2.8.9 w/wxWinCE;
User avatar
T-Rex
Moderator
Moderator
Posts: 1248
Joined: Sat Oct 23, 2004 9:58 am
Location: Zaporizhzhya, Ukraine
Contact:

Post by T-Rex »

А елси wxTheApp->Yield() вызвать в деструкторе после Notify(false) и удалением сокета разве сообщения в очереди не обработаются?
m1t0z
Knows some wx things
Knows some wx things
Posts: 25
Joined: Sat Aug 16, 2008 9:03 am

Post by m1t0z »

radcapricorn wrote:Судя по всему, так и есть - остается какая-то связка между сокетом и обработчиком, причем второй удаляется явно раньше первого.

Можно попробовать реализовать Destroy() для обработчика вот так:

Code: Select all

wxAppTraits *traits = wxTheApp ? wxTheApp->GetTraits() : 0;
if (traits)
{
    traits->ScheduleForDestroy(this);
}
else
{
    delete this;
}
Спасибо! Помогло )

p.s. В официальный мануалах описание wxAppTraits::ScheduleForDestroy() не нашел, только в хидерах библиотеки непосредственно. Много еще такого скрытого богатсва в wx?
m1t0z
Knows some wx things
Knows some wx things
Posts: 25
Joined: Sat Aug 16, 2008 9:03 am

Post by m1t0z »

T-Rex wrote:А елси wxTheApp->Yield() вызвать в деструкторе после Notify(false) и удалением сокета разве сообщения в очереди не обработаются?
Как ни странно, но это не помогло...
radcapricorn
Experienced Solver
Experienced Solver
Posts: 70
Joined: Fri Nov 07, 2008 4:25 pm
Location: Saint-Petersburg, Russia

Post by radcapricorn »

m1t0z,
p.s. В официальный мануалах описание wxAppTraits::ScheduleForDestroy() не нашел, только в хидерах библиотеки непосредственно. Много еще такого скрытого богатсва в wx?
Да прилично, если в сырцах поковыряться :-)

T-Rex,

Насчет Yield() и почему оно не помогает - тут уж не знаю. Будет время - покопаюсь в исходниках "на пощупать".
win xp pro sp3/VS Express 2008/MinGW;
win Vista Ultimate/VS 2005;
Debian Lenny/gcc/cegcc-mingw32ce;
wxWidgets-2.8.9 w/wxWinCE;
User avatar
Billy Bones
In need of some credit
In need of some credit
Posts: 3
Joined: Mon Nov 13, 2006 7:54 pm
Location: Moscow, Russia
Contact:

Post by Billy Bones »

Можно еще попробовать вызвать вполне себе документированный метод wxSocketBase::Close(). Он прибивает сообщения в очереди.
radcapricorn
Experienced Solver
Experienced Solver
Posts: 70
Joined: Fri Nov 07, 2008 4:25 pm
Location: Saint-Petersburg, Russia

Post by radcapricorn »

Оживляем тему? :-)

Code: Select all

wxSocketBase::Close
void Close()

(1) ...Upon socket destruction, Close is automatically called...

Remark/Warning

(2) Although Close immediately disables events for the socket, it is possible that event messages may be waiting in the application's event queue. The application must therefore be prepared to handle socket event messages even after calling Close.
Из (1) следует отсутствие необходимости явного вызова Close().

Из (2) - наличие уже назначенных (до вызова Close()) событий, которые никто вовсе и не прибивает.
win xp pro sp3/VS Express 2008/MinGW;
win Vista Ultimate/VS 2005;
Debian Lenny/gcc/cegcc-mingw32ce;
wxWidgets-2.8.9 w/wxWinCE;
Post Reply