Удаление динамически выделенной памяти
От: kupaloff  
Дата: 01.05.13 19:42
Оценка: -1 :)
Здравствуйте!
При удалении памяти с помощью оператора delete, которая была выделена с помощью оператора new под экземпляр класса, программа падает.
Все указатели хранятся в CArray<type, type>. Падает не стабильно...а при разных условиях использования программы. Причем до падения
все циклы удаления элементов успешно выполняются.

Подскажите пожалуйста, в чем может быть проблема и как поймать ее причину...
Спасибо!


iCnt = m_oAdvisedWebBrowser2.GetCount();
for(int k = iCnt - 1; k >= 0; k--)
{
    CWebBrowser2* pWebBrowser2 = m_oAdvisedWebBrowser2.GetAt(k);
    if(NULL != pWebBrowser2)
    {
        if(pWebBrowser2->m_bDelete == TRUE)
        {
            delete pWebBrowser2;
            m_oAdvisedWebBrowser2.RemoveAt(k);
        }
        else{}
    }
    else
    {
        m_oAdvisedWebBrowser2.RemoveAt(k);
    }
}
Re: Удаление динамически выделенной памяти
От: __kot2  
Дата: 01.05.13 20:49
Оценка:
это самый дурацко оформленный код, который я когда либо видел за свою жизнь

04.05.13 00:39: ветка заблокирована: один из самых неконструктивных советов, которые модератор когда-либо видел
Re: Удаление динамически выделенной памяти
От: LaptevVV Россия  
Дата: 02.05.13 04:29
Оценка: :)
Здравствуйте, kupaloff, Вы писали:

K>
K>iCnt = m_oAdvisedWebBrowser2.GetCount();
K>for(int k = iCnt - 1; k >= 0; k--)
K>{
K>    CWebBrowser2* pWebBrowser2 = m_oAdvisedWebBrowser2.GetAt(k);
K>    if(NULL != pWebBrowser2)
K>    {
K>        if(pWebBrowser2->m_bDelete == TRUE)
K>        {
K>            delete pWebBrowser2;
K>            m_oAdvisedWebBrowser2.RemoveAt(k);
K>        }
K>        else{}
K>    }
K>    else
K>    {
K>        m_oAdvisedWebBrowser2.RemoveAt(k);
K>    }
K>}
K>

1. А если GetCount() вернет 0 ?
2. А если GetAt(k) возвращает "левый" адрес ?
3. А если RemoveAt(k) удаляет что-то не то ?
Короче, информации в твоем коде — ноль. Поскольку ты не приводишь код, где ты память выделяешь и что ты там размещаешь.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re: Удаление динамически выделенной памяти
От: okman Беларусь https://searchinform.ru/
Дата: 02.05.13 04:41
Оценка:
Здравствуйте, kupaloff, Вы писали:

K>При удалении памяти с помощью оператора delete, которая была выделена с помощью оператора new под экземпляр класса, программа падает.


pWebBrowser2 — это указатель на COM-объект, реализующий IWebBrowser2 ?
Если да, то его нельзя удалять через delete, нужно использовать стандартный метод IUnknown::Release.
Re: Удаление динамически выделенной памяти
От: ononim  
Дата: 02.05.13 10:24
Оценка:
K>[ccode]
K>iCnt = m_oAdvisedWebBrowser2.GetCount();
K>for(int k = iCnt — 1; k >= 0; k--)
K>{
K> CWebBrowser2* pWebBrowser2 = m_oAdvisedWebBrowser2.GetAt(k);
.................

вы случайно не из Редмонта пишете?
Как много веселых ребят, и все делают велосипед...
Re[2]: Удаление динамически выделенной памяти
От: kupaloff  
Дата: 02.05.13 17:56
Оценка: :)
Здравствуйте, LaptevVV, Вы писали:

LVV>1. А если GetCount() вернет 0 ?

LVV>2. А если GetAt(k) возвращает "левый" адрес ?
LVV>3. А если RemoveAt(k) удаляет что-то не то ?
LVV>Короче, информации в твоем коде — ноль. Поскольку ты не приводишь код, где ты память выделяешь и что ты там размещаешь.

1. если GetCount() вернет 0 — то цикл не начнется
2. если GetAt(k) возвращает "левый" адрес — ВОТ! Это как это отследить...
3. если RemoveAt(k) удаляет что-то не то — что значит не то, удаляется k элемент из массива

вот код выделения памяти:

typedef CArray<CWebBrowser2*, CWebBrowser2*> CAdvisedWebBrowser2;
CAdvisedWebBrowser2 m_oAdvisedWebBrowser2;

...

TRY
{

    ...

    CWebBrowser2* pWebBrowser2 = NULL;
    pWebBrowser2 = new CWebBrowser2(this);
    if(NULL != pWebBrowser2)
    {
        m_oAdvisedWebBrowser2.Add(pWebBrowser2);
    }

    ...
}
CATCH(CMemoryException, ex)
{
    TCHAR cause[MAX_PATH] = {0};

    ex->GetErrorMessage(cause, MAX_PATH);

    TCHAR log_mes[100 + MAX_PATH] = {0};
    sprintf(log_mes, _T("OnIETimer CMemoryException %s "), cause);
    AddToLog(log_mes);

    AfxAbort();
}
END_CATCH


CWebBrowser2* — это класс
Re[2]: Удаление динамически выделенной памяти
От: kupaloff  
Дата: 02.05.13 18:00
Оценка:
Здравствуйте, okman, Вы писали:

O>Здравствуйте, kupaloff, Вы писали:


K>>При удалении памяти с помощью оператора delete, которая была выделена с помощью оператора new под экземпляр класса, программа падает.


O>pWebBrowser2 — это указатель на COM-объект, реализующий IWebBrowser2 ?

O>Если да, то его нельзя удалять через delete, нужно использовать стандартный метод IUnknown::Release.

нет, но это указатель на класс, наследуемый от CCmdTarget, который подключается к событиям окна IE и перехватывает сообщения от него
Re[2]: Удаление динамически выделенной памяти
От: kupaloff  
Дата: 02.05.13 18:13
Оценка:
Здравствуйте, __kot2, Вы писали:

__>это самый дурацко оформленный код, который я когда либо видел за свою жизнь


И в чем же выражается самый дурацко оформленный код?
Re[2]: Удаление динамически выделенной памяти
От: kupaloff  
Дата: 02.05.13 18:14
Оценка:
Здравствуйте, ononim, Вы писали:

K>>[ccode]

K>>iCnt = m_oAdvisedWebBrowser2.GetCount();
K>>for(int k = iCnt — 1; k >= 0; k--)
K>>{
K>> CWebBrowser2* pWebBrowser2 = m_oAdvisedWebBrowser2.GetAt(k);
O>.................

O>вы случайно не из Редмонта пишете?


Я не знаю про что вы говорите, извините...
Re[3]: Удаление динамически выделенной памяти
От: okman Беларусь https://searchinform.ru/
Дата: 02.05.13 18:26
Оценка:
Здравствуйте, kupaloff, Вы писали:

K>нет, но это указатель на класс, наследуемый от CCmdTarget, который подключается к событиям окна IE и перехватывает сообщения от него


А можете привести объявление данного класса ?
Re[4]: Удаление динамически выделенной памяти
От: kupaloff  
Дата: 02.05.13 18:50
Оценка:
Здравствуйте, okman, Вы писали:

O>Здравствуйте, kupaloff, Вы писали:


K>>нет, но это указатель на класс, наследуемый от CCmdTarget, который подключается к событиям окна IE и перехватывает сообщения от него


O>А можете привести объявление данного класса ?


Описание данного класса в прилагаемых файлах...
http://files.rsdn.ru/59447/WebBrowser2.h
http://files.rsdn.ru/59447/WebBrowser2.cpp
Re[3]: Удаление динамически выделенной памяти
От: LaptevVV Россия  
Дата: 02.05.13 19:47
Оценка:
Здравствуйте, kupaloff, Вы писали:

K>Здравствуйте, LaptevVV, Вы писали:


LVV>>1. А если GetCount() вернет 0 ?

LVV>>2. А если GetAt(k) возвращает "левый" адрес ?
LVV>>3. А если RemoveAt(k) удаляет что-то не то ?
LVV>>Короче, информации в твоем коде — ноль. Поскольку ты не приводишь код, где ты память выделяешь и что ты там размещаешь.

K>1. если GetCount() вернет 0 — то цикл не начнется

А если GetCount вернет самое большое целое? Тим iCnt неизвестен. Он знаковый или беззнаковый?
K>2. если GetAt(k) возвращает "левый" адрес — ВОТ! Это как это отследить...
Надо знать, как выделяется. А то ты закладываешься на проверку NULL, а new() — то может вернуть исключение bad_alloc
K>3. если RemoveAt(k) удаляет что-то не то — что значит не то, удаляется k элемент из массива
А как он удаляется?
Не проще ли вместо динамических массивов просто vector использовать?
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)------------------------------------а если = NULL ? :)
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* — это класс

1. С одной стороны — ловишь исключение CMemoryException, с другой стороны — проверяешь на NULL.
2. А что делает метод Add ? Опять же, не проще ли vector использовать?
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re: Удаление динамически выделенной памяти
От: Константин Россия  
Дата: 02.05.13 20:00
Оценка: 5 (1) +2
Здравствуйте, kupaloff, Вы писали:

K>Подскажите пожалуйста, в чем может быть проблема и как поймать ее причину...

K>Спасибо!

Проблема в том, что приложение некорректно работает с памятью. Судя по коду, это не удивительно. Рецепт следующий:

Выкинуть CArray => std::vector<std::shared_ptr<...>> (чтобы контейнер владел данными)
Велосипед с удалением выкинуть и заменить на стандартный => std::remove_if + std::vector.erase

После этого ошибка или исчезнет, или будет ясно, что она в другом месте
Re[3]: Удаление динамически выделенной памяти
От: __kot2  
Дата: 03.05.13 01:04
Оценка: -4 :)
Здравствуйте, kupaloff, Вы писали:
K>Здравствуйте, __kot2, Вы писали:
__>>это самый дурацко оформленный код, который я когда либо видел за свою жизнь
K>И в чем же выражается самый дурацко оформленный код?

K>
K>iCnt = m_oAdvisedWebBrowser2.GetCount(); - венгерская нотация в 2013ом году? она всегда была идиотской, но еще в 90ых даже самые упертые от нее отказались. 
почему cnt а не count? может это cunt? зачем надо было вычислять icnt?
webbrowser2 - офигительное название. 2 это что?
GetCount() - это что за контейнер такой? самописный? зачем? почему паскалевское именование ф-ий? это ж С++?

K>for(int k = iCnt - 1; k >= 0; k--) // почему цикл задом наперед? чем это вызвано? чтобы cnt постоянно не считать? так его вычисление и так вынесено наружу. почему k ? что это за протест против кошерного i ?
K>{
K>    CWebBrowser2* pWebBrowser2 = m_oAdvisedWebBrowser2.GetAt(k); // хотя бы ссылку, чтоли возвращали вместо указателя. а имена-то какие красивые: с двоечкой в два раза красивее и С торчит впереди имени класса, еще и звезда криво стоит. летопа прямо
K>    if(NULL != pWebBrowser2) // хоть бы пробелы, чтоли ставили if ( ...
K>    {
K>        if(pWebBrowser2->m_bDelete == TRUE) // какое нафиг TRUE в С++? что за бред вообще заводить флаг удаления прямо в браузер? не надо смешивать классы
K>        {
K>            delete pWebBrowser2;       // ниажидана
K>            m_oAdvisedWebBrowser2.RemoveAt(k); // общепринято, что контейнеры тут сами вообще-то все удаляют
K>        }
K>        else{} // что тут имелось в виду? продолжение следует?
K>    }
K>    else
K>    {
K>        m_oAdvisedWebBrowser2.RemoveAt(k); // что это за копипаста? мысль нельзя было яснее выразить, когда удаляем, а когда нет?
K>    }
K>} где тут вообще С++ ? это какой-то ядреный самопал
K>
Re[4]: Удаление динамически выделенной памяти
От: kpcb Россия  
Дата: 03.05.13 04:18
Оценка: +2
Здравствуйте, __kot2, Вы писали:

K>> венгерская нотация в 2013ом году? она всегда была идиотской, но еще в 90ых даже самые упертые от нее отказались.

Смелое заявление

__>GetCount() — это что за контейнер такой? самописный? зачем? почему паскалевское именование ф-ий? это ж С++?

Знакомься, CAtlArray

K>>} где тут вообще С++ ? это какой-то ядреный самопал

Если заменить удаление элементов по одному на RemoveAll после цикла и лишний else (судя по всему там был какой-то код, который _не_ нужен для примера), то это вполне нормальное оформление программы, написанной для Win + MFC.
Re[4]: Удаление динамически выделенной памяти
От: Кодт Россия  
Дата: 03.05.13 20:55
Оценка:
Здравствуйте, LaptevVV, Вы писали:

K>>1. если GetCount() вернет 0 — то цикл не начнется

LVV>А если GetCount вернет самое большое целое? Тим iCnt неизвестен. Он знаковый или беззнаковый?

Во-первых, если GetCount() вернёт что-то слишком большое, это уже свидетельствует о поломке в программе. Откуда там контейнер с несколькими миллиардами элементов?
Во-вторых, из венгерской нотации следует, что iCnt — это int.
В-третьих, если он даже unsigned и >INT_MAX, то ничего страшного: int i=iCnt-1, целочисленное переполнение, получим отрицательное число, не попадём в цикл.

K>>2. если GetAt(k) возвращает "левый" адрес — ВОТ! Это как это отследить...

LVV>Надо знать, как выделяется. А то ты закладываешься на проверку NULL, а new() — то может вернуть исключение bad_alloc

Если возникает bad_alloc, то элемент не попадёт в контейнер

K>>3. если RemoveAt(k) удаляет что-то не то — что значит не то, удаляется k элемент из массива

LVV>А как он удаляется?
LVV>Не проще ли вместо динамических массивов просто vector использовать?

В ATL/MFC программе очень естественно использовать CArray, а не std::vector. Разница между ними невелика.

LVV>1. С одной стороны — ловишь исключение CMemoryException, с другой стороны — проверяешь на NULL.


Вот это действительно перестраховка, память о компиляторах VC5- (до стандарта 98), где new был небросающим.


LVV>2. А что делает метод Add ? Опять же, не проще ли vector использовать?


Интересно, а что мог бы делать метод Add у MFC'шного контейнера CArray?
Перекуём баги на фичи!
Re[2]: Удаление динамически выделенной памяти
От: Кодт Россия  
Дата: 03.05.13 21:07
Оценка:
Здравствуйте, Константин, Вы писали:

К>Выкинуть CArray => std::vector<std::shared_ptr<...>> (чтобы контейнер владел данными)


... и заодно проследить, чтобы нигде не остались голые указатели на CWebBrowser2. (А заполучить голый указатель — как нефиг делать, это же библиотечный класс, а не наш самописный полностью подконтрольный).
Если проблема с кривым владением существует, то она как раз состоит в том, что кто-то владеет этими объектами, помимо контейнера. Ну и какая разница, будем мы вручную реализовывать монопольное владение объектов контейнером, или автоматизируем монопольное владение с помощью shared_ptr?

Хотя, если где-то есть явное воровство указателей непосредственно из контейнера, то shared_ptr поможет найти это место, сломав компиляцию.
Перекуём баги на фичи!
Re: Удаление динамически выделенной памяти
От: Кодт Россия  
Дата: 03.05.13 21:31
Оценка:
Здравствуйте, kupaloff, Вы писали:

K>При удалении памяти с помощью оператора delete, которая была выделена с помощью оператора new под экземпляр класса, программа падает.

K>Все указатели хранятся в CArray<type, type>. Падает не стабильно...а при разных условиях использования программы. Причем до падения
K>все циклы удаления элементов успешно выполняются.

Возможные причины падения:
1) объект прямо в данный момент кем-то используется, — например, там выполняется асинхронный обмен по http (браузер же)
2) реентер в функцию, в которой выполняется очистка массива
Реентер может быть многопоточным или однопоточным. Однопоточный реентер возникает следующим образом:
— вошли в функцию
— начали удалять первый попавшийся объект
— из его деструктора снова вошли в эту функцию
— снова начали удалять объект...

От многопоточных реентеров спасают мьютексы CCriticalSection.
От однопоточных — двухфазное удаление:
CAdvisedWebBrowser2& arr = m_oAdvisedWebBrowser2; // боже, какие ужасные идентификаторы типа и переменной...
CAdvisedWebBrowser2 arr_to_delete;

int const n = arr.GetCount();
// первая фаза: переносим удаляемые объекты во временный массив
for(int i=0; i!=n; ++i)
{
  CAdvisedWebBrowser2*& obj = arr[i]; // ссылка на элемент массива
  if(obj && obj->m_bDelete) { arr_to_delete.Add(obj); obj = NULL; } // обнулим этот элемент
}

// вторая фаза: сжимаем исходный массив (повода для реентера ещё нет...)
for(int i=n-1; i>=0; --i)
  if(!arr[i]) arr.RemoveAt(i);

// третья фаза: исходный массив уже свободен и может быть переиспользован
for(int i=0, nd=arr_to_delete.GetCount(); i!=nd; ++i)
  delete arr_to_delete[i];

От реентера это не избавит, но сделает его безопасным.

Однако, если в программе существуют реентеры, — это значит, что в ней есть макароны потоков исполнения. И от них нужно избавляться, тщательно осмысливая, что в какой момент ДОЛЖНО происходить по замыслу, а не "должно бы происходить в имеющемся коде".
Отдавать уничтожение CCmdTarget'ов на откуп деструкторам (их самих или их владельцев) самонадеянно. Там и виндоуз выполняет обряд умерщвления, и MFC к нему прикладывается... в общем, я сейчас не готов развернуть тему, что делать и кого виновать (для этого мне надо ставить винды и студию, и вспоминать былое).
Перекуём баги на фичи!
Re[5]: Удаление динамически выделенной памяти
От: LaptevVV Россия  
Дата: 04.05.13 05:54
Оценка:
Здравствуйте, Кодт, Вы писали:

Да вопросы были скорее риторические — привычка студентам задавать, чтобы думали сначала...
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re[2]: Удаление динамически выделенной памяти
От: Аноним  
Дата: 04.05.13 17:47
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Однако, если в программе существуют реентеры, — это значит, что в ней есть макароны потоков исполнения. И от них нужно избавляться, тщательно осмысливая, что в какой момент ДОЛЖНО происходить по замыслу, а не "должно бы происходить в имеющемся коде".

К>Отдавать уничтожение CCmdTarget'ов на откуп деструкторам (их самих или их владельцев) самонадеянно. Там и виндоуз выполняет обряд умерщвления, и MFC к нему прикладывается... в общем, я сейчас не готов развернуть тему, что делать и кого виновать (для этого мне надо ставить винды и студию, и вспоминать былое).

Проблема более-менее определилась, после логирования и использования SetUnhandledExceptionFilter. Каким-то образом самопроизвольно вызывается деструктор объекта (причем 2 раза), но указатель на объект не удаляется из контейнера. Каждый вызов деструктора логировался с указанием значения указателя объекта вызывавшего его. И когда в программе мы доходим до момента его удаления, согласно логике работы программы...то происходит ТРЕТИЙ вызов деструктора уже удаленного объекта, на что мы получаем вот такую вот штуку:

23:12:53 ae8 ****************************************************
12:14:04 5e4 *** A Programm Fault occured:
12:14:04 5e4 *** Error code C0000005: EXCEPTION_ACCESS_VIOLATION
12:14:04 5e4 ****************************************************


Удаляется память под объекты только в единственном месте, в одной функции, реентер которой регулируется мьютексом, т.е. запустить ее второй раз не удастся ни в другом потоке, ни в этом же, пока она не закончит работу и не освободит мьютекс.

Объекты данного класс присоединяется к событиям открытых окон IE через DIID_DWebBrowserEvents2, соответственно сколько окон(вкладок) столько и объектов. Удаление объекта по логике работы программы происходит после анализа открытых окон IE и сравнения их с хранимыми в контейнере, соответственно если окна нет, а в контейнере оно есть, то удаляется память и удаляется элемент контейнера.

Возникают следующие вопросы:
1) почему деструктор вызывается дважды
2) каким образом и кем деструктор может вызываться, если он точно вызывается не кодом, так как это делается потом
3) "Отдавать уничтожение CCmdTarget'ов на откуп деструкторам (их самих или их владельцев) самонадеянно. Там и виндоуз выполняет обряд умерщвления, и MFC к нему прикладывается... в общем, я сейчас не готов развернуть тему, что делать и кого виновать (для этого мне надо ставить винды и студию, и вспоминать былое)." Поясните пожалуйста это более подробно, может надо совершить какие-то действия или...что?

Часть лога программы где видно вызов деструкторов (неожиданно) и удаление согласно логике работы программы ( где и ожидается удаление):

12:13:49 5e4 OnIETimer
12:13:49 5e4 OnIETimer Mutex created
12:13:49 5e4 OnIETimer Get openning IE windows
12:13:50 128c send_data_thread DELAY = 24 send_data_stop = 0
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 OnIETimer Add new web browser SetIdispatchPointer
12:13:50 5e4 OnIETimer Add new web browser setHWND
12:13:50 5e4 OnIETimer Add new web browser Attach
12:13:50 1228 SetFlag
12:13:50 1228 SendData Return
12:13:50 1228 send_data_thread_2 return
12:13:50 5e4 OnIETimer Add new web browser SendData
12:13:50 5e4 EA5BE0 URL == NULL
12:13:50 5e4 EA5BE0 pWebBrowser != NULL
12:13:50 5e4 EA5BE0 URL_1 == NULL
12:13:50 5e4 OnIETimer Add new web browser Add — добавление объекта в контейнер
12:13:50 5e4 OnIETimer Add new web browser ok
12:13:50 5e4 OnIETimer Delete cycle start
12:13:50 5e4 OnIETimer m_oAdvisedWebBrowser2 count is 3
12:13:50 5e4 OnIETimer m_oAdvisedWebBrowser2 return 2 element
12:13:50 5e4 OnIETimer NOT Delete monitoring IE window
12:13:50 5e4 OnIETimer m_oAdvisedWebBrowser2 return 1 element
12:13:50 5e4 OnIETimer NOT Delete monitoring IE window
12:13:50 5e4 OnIETimer m_oAdvisedWebBrowser2 return 0 element
12:13:50 5e4 OnIETimer NOT Delete monitoring IE window
12:13:50 5e4 OnIETimer Left 3 monitoring IE windows
12:13:50 5e4 OnIETimer Mutex closed
12:13:50 5e4 OnIETimer Return
12:13:50 5e4 EA5BE0 Checking interface pointer — 1 вызов деструктора
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 вызов деструктора
12:14:04 5e4 EXCEPTION_ACCESS_VIOLATION — сработало Unhandled Exception
12:14:04 5e4 ****************************************************
12:14:04 5e4 *** A Programm Fault occured:
12:14:04 5e4 *** Error code C0000005: EXCEPTION_ACCESS_VIOLATION
12:14:04 5e4 ****************************************************
12:14:04 5e4 *** Address: 00EA5BE0
12:14:04 5e4 *** Flags: 00000000
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.