Memory Leak при выгрузке dll Topic is solved

Это русская секция форума wxWidjets. В этой секции вы можете обсуждать любые вопросы, связанные с wxWidgets на вашем родном языке.
skozlov
Knows some wx things
Knows some wx things
Posts: 26
Joined: Tue Dec 16, 2008 12:54 pm

Memory Leak при выгрузке dll

Post by skozlov » Mon Jun 15, 2009 10:48 am

Столкнулся с такой проблемой.

Есть хост приложение для Win с поддержкой модулей.

Набросал простой модуль (msvc 2008), использующий wxWidgets.

и простой wxApp:

Code: Select all


....

IMPLEMENT_APP_NO_MAIN(Application)


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

  MainWindow *win = new MainWindow;
  win->Show(true);
  SetTopWindow(win);

  return true;

}

модуль загружается без проблем, а вот при выгрузке модуля
вылазит memory dump по случаю утечек в памяти.

Но. Application нигде не создается и не используется. Точнее
wxWidgets вообще не используется. Реализована только пара классов: wxApp и wxFrame, а их инстанцирование нигде не производится равно как и инициализация wxWidgets.

Пробвал компилировать с монилитной 2.8.9, монолитной 3.0, и "обычной" 3.0. Все версии debug.

Никто не сталкивался с таким?

Memory leaks происходят и вслучае инициализации wxWidgets:

Code: Select all


...

DWORD WINAPI ThreadProc(LPVOID lpParameter)
{

  wxApp::SetInstance(new Application);
  wxEntry(module_instance, NULL, 0, 0);
  DebugMessage("End work", 0);

  wxEntryCleanup();

  return true;

}

...
// инициализация
m_guiThread = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);


...

// вызывается при выгрузке модуля

  wxCloseEvent ev(wxEVT_CLOSE_WINDOW);
  ev.SetEventObject(wxTheApp);
  ev.SetCanVeto(false);

  wxWindow *w = wxTheApp->GetTopWindow();
  wxPostEvent(w, ev);

  WaitForSingleObject(m_guiThread, INFINITE);

  CloseHandle(m_guiThread);

Вот что появляется в окне отладки в случае, если wx не используется:
"Anvil.exe": Загружено: "D:\Work\lua_work\ATrader-0.3\build\win32\Debug\ATrader.dll", Символы загружены.
"Anvil.exe": Загружено: "D:\Work\ATrader\AnvilDebug\wxbase290ud_vc_custom.dll", Символы загружены.
"Anvil.exe": Загружено: "C:\WINDOWS\WinSxS\x86_Microsoft.VC90.DebugCRT_1fc8b3b9a1e18e3b_9.0.30729.1_x-ww_f863c71f\msvcp90d.dll", Символы загружены.
"Anvil.exe": Загружено: "C:\WINDOWS\WinSxS\x86_Microsoft.VC90.DebugCRT_1fc8b3b9a1e18e3b_9.0.30729.1_x-ww_f863c71f\msvcr90d.dll", Символы загружены.
"Anvil.exe": Загружено: "D:\Work\ATrader\AnvilDebug\wxmsw290ud_core_vc_custom.dll", Символы загружены.
"Anvil.exe": Загружено: "C:\WINDOWS\WinSxS\x86_Microsoft.VC90.DebugMFC_1fc8b3b9a1e18e3b_9.0.30729.1_x-ww_c94a3a24\mfc90ud.dll", Символы загружены.
"Anvil.exe": Загружено "C:\WINDOWS\system32\msimg32.dll"
"Anvil.exe": Загружено "D:\Work\ATrader\AnvilDebug\boost_thread-vc90-mt-gd-1_38.dll"
"Anvil.exe": Загружено: "C:\WINDOWS\WinSxS\x86_Microsoft.VC90.MFCLOC_1fc8b3b9a1e18e3b_9.0.30729.1_x-ww_b0db7d03\mfc90rus.dll", Двоичный код не был построен с отладочной информацией.
Thread id=2852: ATrader DLL Initialization ...
Thread id=2852 class gui::Gui *@04C13C20: initialization()
Thread id=2852 class gui::Gui *@04C13C20: uninitialization()
Detected memory leaks!
Dumping objects ->
{2405} normal block at 0x04C0CE10, 48 bytes long.
Data: <w x H V S c r o > 77 00 78 00 48 00 56 00 53 00 63 00 72 00 6F 00
{2404} normal block at 0x04C0CDA8, 40 bytes long.
Data: < > 00 00 00 00 CD CD CD CD 10 CE C0 04 CD CD CD CD
{2403} normal block at 0x04C0CD58, 16 bytes long.
Data: <( ! hb > 28 90 B9 03 A8 CD C0 04 E4 21 B7 04 68 62 B9 03
{2400} normal block at 0x04C0CCE8, 48 bytes long.
Data: <w x H S c r o l > 77 00 78 00 48 00 53 00 63 00 72 00 6F 00 6C 00
{2399} normal block at 0x04C0CC80, 40 bytes long.
Data: < > 00 00 00 00 CD CD CD CD E8 CC C0 04 CD CD CD CD
{2398} normal block at 0x04C0CC30, 16 bytes long.
Data: <0 ! hb > 30 CC C0 04 80 CC C0 04 CC 21 B7 04 68 62 B9 03
{2395} normal block at 0x04C0CBC0, 48 bytes long.
Data: <w x V S c r o l > 77 00 78 00 56 00 53 00 63 00 72 00 6F 00 6C 00

// дальше туева хуча

...

"Anvil.exe": Выгружено: "D:\Work\lua_work\ATrader-0.3\build\win32\Debug\ATrader.dll"
"Anvil.exe": Выгружено: "D:\Work\ATrader\AnvilDebug\boost_thread-vc90-mt-gd-1_38.dll"
"Anvil.exe": Выгружено: "C:\WINDOWS\WinSxS\x86_Microsoft.VC90.DebugMFC_1fc8b3b9a1e18e3b_9.0.30729.1_x-ww_c94a3a24\mfc90ud.dll"
"Anvil.exe": Выгружено: "C:\WINDOWS\system32\msimg32.dll"
"Anvil.exe": Выгружено: "D:\Work\ATrader\AnvilDebug\wxmsw290ud_core_vc_custom.dll"
"Anvil.exe": Выгружено: "D:\Work\ATrader\AnvilDebug\wxbase290ud_vc_custom.dll"

...
Здесь Anvil - это хост программа, ATrader - модуль.
WinXp, wxWidgets 2.8.9, wxWidgets-svn, MSVC 9

ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 4152
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Post by ONEEYEMAN » Wed Jun 24, 2009 6:28 am

Доброе,
Пару вопросов:

1. Код с IMPLEMENT_APP_NO_MAIN() принадлежит к библиотеке или к основному модулю?
2. Если wx библиотека не используется, то как попал код с wx в вопрос?
3. Помимо использования библиотеки, используется многозадачность. В рабочей нитке вызываешь GUI?
4. Что говорит отладчик при попытке отследить соответствующий адрес?
5. Какая конфигурация использовалась при сборке wx - DLL or static?

Спасибо.

skozlov
Knows some wx things
Knows some wx things
Posts: 26
Joined: Tue Dec 16, 2008 12:54 pm

Post by skozlov » Wed Jun 24, 2009 10:18 am

ONEEYEMAN wrote:Доброе,
Пару вопросов:

1. Код с IMPLEMENT_APP_NO_MAIN() принадлежит к библиотеке или к основному модулю?
2. Если wx библиотека не используется, то как попал код с wx в вопрос?
3. Помимо использования библиотеки, используется многозадачность. В рабочей нитке вызываешь GUI?
4. Что говорит отладчик при попытке отследить соответствующий адрес?
5. Какая конфигурация использовалась при сборке wx - DLL or static?

Спасибо.
Вам спасибо.

Пара ответов:
1. Не совсем понял, что такое библиотека и основной модуль. Весь приведенный код относится к библиотеке(назовем ее extDll), которая загружается как расширение в стороннюю программу (код которой закрыт).

2. Да, wx не используется в данной ситуации. Но wxWidgets планируется использовать в extDll. А приведенный код - это каркас. Те я реализовал wxApp (Application), но нигде не создавал экземпляра, потом откомпилировал проект, чтобы убедиться, что нет ошибок. Ну а потом ради интереса просто загрузил extDll через хост-приложение (Anvil) и после выгрузки extDll из Anvil получил memory leak.

3. GUI планирую вызывать в отдельном рабочем потоке.

4. Делал, но не помню куда меня это привело. Попробую еще раз.

5. Я пробовал несколько сборок. Лог приведен для wx-svn x32 dll, которую собирал visual studio 2008 из проекта в дистрибутиве wxWidgets - тупо открыл build\msw\wx_vc9.snl и собрал Debug DLL/Win32. Потом пробовал монолитную сборку:

Code: Select all

nmake -f makefile.vc SHARED=1 MONOLITHIC=1 BUILD=debug VENDOR=x32_qh
и еще монолитную wxWidgets-2.8.9. Т.е. я всегда использовал dll.

Вот такие дела.
WinXp, wxWidgets 2.8.9, wxWidgets-svn, MSVC 9

skozlov
Knows some wx things
Knows some wx things
Posts: 26
Joined: Tue Dec 16, 2008 12:54 pm

Post by skozlov » Sat Jun 27, 2009 6:23 am

Хм.
Собрал wx-svn x32 debug custom dll.
Утечек нет..
Странно. Мб в сборке монолитной dll что-то не так?
WinXp, wxWidgets 2.8.9, wxWidgets-svn, MSVC 9

ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 4152
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Post by ONEEYEMAN » Sun Jun 28, 2009 4:58 am

Доброе,
Скорее всего это многозадачность а не сборка.
Все что нужно сделать - убрать GUI из вторичной нитки. GUI calls не рекомендуется производить из worker thread, только из main thread.

А у тебя ситуация еще веселее: помимо многозадачности еще и ДЛЛ...

Спасибо

skozlov
Knows some wx things
Knows some wx things
Posts: 26
Joined: Tue Dec 16, 2008 12:54 pm

Post by skozlov » Sun Jun 28, 2009 6:58 am

А как-же тогда ГУЙ запускать? В основном потоке крутится хост-приложение и если использовать прием с

Code: Select all

...

wxEntry(module_instance, NULL, 0, 0);
...
то wx будет блокировать его.

Кстати, эксперимент я проводил именно запуском GUI в рабочем потоке..
WinXp, wxWidgets 2.8.9, wxWidgets-svn, MSVC 9

ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 4152
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Post by ONEEYEMAN » Sun Jun 28, 2009 5:04 pm

Доброе,
Все дело в том что вся документация и все рекомендации core-dev говорят: вся графика должна запускаться и работать в основной нитке, рабочая нитка предназначена для работы и общается с основной с помошью собыитй, которые говорят графическому интерфейсу когда произвести обновление экрана-данных.

Спасибо.

skozlov
Knows some wx things
Knows some wx things
Posts: 26
Joined: Tue Dec 16, 2008 12:54 pm

Post by skozlov » Mon Jun 29, 2009 6:13 am

Для wx поток, в котором была произведена инициализация, и будет основным для GUI. Инициализация и все связанные операции (такие как цикл сообщений, отрисовка виджетов и т.д.) будут происходить в контексте этого потока. Так что можно сказать, что это и будет основным потоком (для wxWidgets). Тем более в вики, да и на форуме(en) для использования wxWidgets в dll описывают прием с созданием отдельного потока.

Хотя мб я что-то не так понял.

В любом случае, проблему с утечкой памяти я пока придумать не могу..

Но все-равно спасибо за сотрудничество)
WinXp, wxWidgets 2.8.9, wxWidgets-svn, MSVC 9

ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 4152
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Post by ONEEYEMAN » Mon Jun 29, 2009 11:16 am

Доброе,
Проблема в том что у тебя создается и ДЛЛ и нитк(и), а DLL и multi-thread - это 2 совершенно разных понятия...

Спасибо

skozlov
Knows some wx things
Knows some wx things
Posts: 26
Joined: Tue Dec 16, 2008 12:54 pm

Post by skozlov » Tue Jun 30, 2009 8:14 am

То есть проблема не решаема?)
WinXp, wxWidgets 2.8.9, wxWidgets-svn, MSVC 9

ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 4152
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Post by ONEEYEMAN » Tue Jun 30, 2009 3:48 pm

Hm,
Take the GUI out from worker thread...

Thank you.

skozlov
Knows some wx things
Knows some wx things
Posts: 26
Joined: Tue Dec 16, 2008 12:54 pm

Post by skozlov » Wed Jul 01, 2009 3:55 am

Хорошо. А как это сделать?
По идее надо обрабатывать сообщения wxWidgets самому...

Спасибо
WinXp, wxWidgets 2.8.9, wxWidgets-svn, MSVC 9

borr_1
Super wx Problem Solver
Super wx Problem Solver
Posts: 362
Joined: Wed Mar 07, 2007 8:10 am
Location: Russia, Shakhty

Post by borr_1 » Wed Jul 01, 2009 4:28 am

В thread вынеси только логику и все.

skozlov
Knows some wx things
Knows some wx things
Posts: 26
Joined: Tue Dec 16, 2008 12:54 pm

Post by skozlov » Wed Jul 01, 2009 2:49 pm

я так не могу сделать. wx message loop блокирует обработку сообщений хост-приложения. Поэтому надо либо запускать wx в отдельном потоке, либо самому обрабатывать сообщения wx в основном потоке (не блокируя цикл обработки сообщений хост-приложения). Других вариантов я придумать не могу.
Но как сделать эту обработку я не знаю.
WinXp, wxWidgets 2.8.9, wxWidgets-svn, MSVC 9

ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 4152
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Post by ONEEYEMAN » Wed Jul 01, 2009 6:07 pm

Are you writing a plug-in? If yes, there is a good example on how to write a plug-in for Adobe...

Just search on google.

Thank you.

Post Reply