Здравствуйте, Аноним, Вы писали:
А>Удаляется память под объекты только в единственном месте, в одной функции, реентер которой регулируется мьютексом, т.е. запустить ее второй раз не удастся ни в другом потоке, ни в этом же, пока она не закончит работу и не освободит мьютекс.
Мьютекс не защищает от однопоточного реентера. Тут нужны гарантии иного рода — что функция не будет вызвана рекурсивно (собственно, реентер — это патологическая рекурсия, которую нужно или избежать, или нейтрализовать).
И кстати, мьютексы в оконном потоке, без полного понимания, что там происходит, — это такая богатая кладовая дедлоков...
Потому что, кроме непосредственно пользовательского мьютекса, там ещё незримо присутствует глобальный синхрообъект — очередь сообщений.
Так что мьютексы — исключительно для огораживания
критических секций кода: прочитать что-нибудь из контейнера, положить что-нибудь в контейнер, — но ни в коем случае не вызывать методы элементов контейнера, которые устроят лавину вызовов и посылок сообщений.
А>Объекты данного класс присоединяется к событиям открытых окон IE через DIID_DWebBrowserEvents2, соответственно сколько окон(вкладок) столько и объектов. Удаление объекта по логике работы программы происходит после анализа открытых окон IE и сравнения их с хранимыми в контейнере, соответственно если окна нет, а в контейнере оно есть, то удаляется память и удаляется элемент контейнера.
А>Возникают следующие вопросы:
А>1) почему деструктор вызывается дважды
Собственно, трижды.
А>2) каким образом и кем деструктор может вызываться, если он точно вызывается не кодом, так как это делается потом
Брекпоинты — наше всё. Поймать все три момента и посмотреть, откуда инициировано действие.
Думаю, что там стоит какое-нибудь m_bAutoDelete, что заставляет фреймворк удалять ненужные, по его мнению, объекты.
Например, самоликвидация объекта CWinThread по заверешении его Run().
А>3) "Отдавать уничтожение CCmdTarget'ов на откуп деструкторам (их самих или их владельцев) самонадеянно. Там и виндоуз выполняет обряд умерщвления, и MFC к нему прикладывается... в общем, я сейчас не готов развернуть тему, что делать и кого виновать
(для этого мне надо ставить винды и студию, и вспоминать былое)." Поясните пожалуйста это более подробно, может надо совершить какие-то действия или...что?
У окон есть событие WM_NCDESTROY, после которого окно уже ни в каком виде не существует, и его объект-представитель — если он больше не нужен, как, например, CView какой-нибудь, можно уничтожать. У потоков такой ключевой момент — завершение Run().
Какие там ещё разновидности CCmdTarget бывают...
А>Часть лога программы где видно вызов деструкторов (неожиданно) и удаление согласно логике работы программы ( где и ожидается удаление):
А>12:13:50 5e4 OnIETimer Add new web browser
А>12:13:50 5e4 OnIETimer Add new web browser if
А>12:13:50 5e4 EA5BE0 OnIETimer new CWebBrowser2 — выделена память и создан объект класса CWebBrowser2
Код в студию!
<>
А>12:13:50 5e4 EA5BE0 Checking interface pointer — 1 вызов деструктора
Код и стек в студию! Что это за загадочное "Checking interface pointer"?
А>12:13:50 5e4 EA5BE0 Start Reset function — работа по условию if при 1 вызове деструктора (в функции самого деструктора)
Код и стек в студию!
А>12:13:50 5e4 EA5BE0 Checking interface pointer — 2 вызов деструктора (условие if уже не сработало)
Код и стек в студию!
Может быть, ещё в первый раз надо было предварительно обнулить указатель или иным способом отвязаться от объекта-владельца.
А то он так и будет дёргать деструктор, пока не надоест.
А>12:13:51 128c send_data_thread_delay_175000
А>12:13:51 128c ServiceDelaySetTimer
А>12:13:51 128c send_data_thread Mutex closed
А>12:14:04 5e4 OnIETimer
А>12:14:04 5e4 OnIETimer Mutex created
А>12:14:04 5e4 OnIETimer Get openning IE windows
А>12:14:04 5e4 OnIETimer Delete cycle start — старт цикла удаления невалидный объектов (данных окон IE уже нет)
А>12:14:04 5e4 OnIETimer m_oAdvisedWebBrowser2 count is 3
А>12:14:04 5e4 OnIETimer m_oAdvisedWebBrowser2 return 2 element
А>12:14:04 5e4 EA5BE0 OnIETimer We going to delete memory — попытка вызвать delete pWebBrowser2, 3 вызов деструктора
Код в студию! Чисто для порядка.
Не в смысле — for(int i=nCnt-1;....) а то место, где принимается решение удалять ненужные объекты.
Здравствуйте, kupaloff,
Есть предположение, что delete не нужно вызывать совем, это сделает за вас фреймворк MFC. Вы работаете с событиями интернет эксплорера через класс-наследник от CCmdTarget. Эта работа идет через СОМ-интерфейсы, и CCmdTarget, который уже содержит поддержку интерфейса IDispatch, автоматически вызовет нечто наподобие delete this в OnFinalRelease(), удаляя сам себя по обнулению счетчика ссылок.
Я писал на MFC достаточно давно и сейчас точно не скажу. Попробуйте для начала почитать статью
здесьАвтор(ы): Тимофей Чадов
, также можете посмотреть пример
здесь. И, похоже, вот
здесь у человека была похожая проблема, может, вам помогут ответы.
Здравствуйте, kupaloff, Вы писали:
Купалов! Нееште карри перед сном!!!
K>вот код выделения памяти:
K>K>typedef CArray<CWebBrowser2*, CWebBrowser2*> CAdvisedWebBrowser2;
K>CAdvisedWebBrowser2 m_oAdvisedWebBrowser2;
K>...
K>TRY
K>{
K> ...
K> CWebBrowser2* pWebBrowser2 = NULL;
K> pWebBrowser2 = new CWebBrowser2(this);
K> if(NULL != pWebBrowser2)
K> {
K> m_oAdvisedWebBrowser2.Add(pWebBrowser2);
K> }
K> ...
K>}
K>CATCH(CMemoryException, ex)
K>{
K> TCHAR cause[MAX_PATH] = {0};
ex->>GetErrorMessage(cause, MAX_PATH);
K> TCHAR log_mes[100 + MAX_PATH] = {0};
K> sprintf(log_mes, _T("OnIETimer CMemoryException %s "), cause);
K> AddToLog(log_mes);
K> AfxAbort();
K>}
K>END_CATCH
K>
K>CWebBrowser2* — это класс