Есть приложение на ATL, которое показало утечку 2-х байт памяти (стандартными средствами crtdbg.h). Я вырезал из него все что можно. Осталось только это (сорри, отступы другой форум порезал):
class CMyWindow : public CWindowImpl<CMyWindow>
{
public:
// Optionally specify name of the new Windows class
DECLARE_WND_CLASS("MyName")
// If this macro is not specified in your
// class, ATL will generate a class name
BEGIN_MSG_MAP(CMyWindow)
MESSAGE_HANDLER(WM_PAINT, OnPaint)
END_MSG_MAP()
LRESULT OnPaint(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
// Do some painting code
return 0;
}
};
//
extern "C" int WINAPI _tWinMain(HINSTANCE /*hInstance*/, HINSTANCE hPrevInstance, LPTSTR /*lpCmdLine*/, int nShowCmd)
{
#ifdef _DEBUG
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF);
#endif
{
ATLASSERT(AUX_SUCCEEDED(OleInitialize(0) == S_OK));
AtlAxWinInit();
//srand(GetTickCount());
{
CMyWindow w;
w.Create(0);
w.DestroyWindow();
}
AtlAxWinTerm();
OleUninitialize();
}
#ifdef _DEBUG
if (_CrtDumpMemoryLeaks())
::MessageBeep(MB_ICONEXCLAMATION);
#endif
}
Если закомментировать "w.Create(0);", то утечки нет. Если оставить, то утечка такая:
Detected memory leaks!
Dumping objects ->
{49} normal block at 0x00944D70, 2 bytes long.
Data: < > D8 C2
Object dump complete.
Имя файла и строку, где память выделяетя, оно определить не может.
Потом я создал другое приложение, вот такое:
#define WIN32
#define _WINDOWS
#define _CRTDBG_MAP_ALLOC
#define _ATL_MIN_CRT
#define _DEBUG
#include <windows.h>
//#include <stdlib.h>
//#include <crtdbg.h>
#include <comutil.h>
#include <stdio.h>
#include <tchar.h>
#include <atlbase.h>
#include <atlwin.h>
#include <windows.h>
// this code is from MSDN
// ms-help://MS.MSDNQTR.2003APR.1033/vccore/html/_atl_Implementing_a_Window_with_CWindowImpl.htm
// "Implementing a Window with CWindowImpl"
class CMyWindow : public CWindowImpl<CMyWindow>
{
public:
// Optionally specify name of the new Windows class
DECLARE_WND_CLASS("MyName")
// If this macro is not specified in your
// class, ATL will generate a class name
BEGIN_MSG_MAP(CMyWindow)
MESSAGE_HANDLER(WM_PAINT, OnPaint)
END_MSG_MAP()
LRESULT OnPaint(UINT nMsg, WPARAM wParam,LPARAM lParam, BOOL& bHandled)
{
// Do some painting code
return 0;
}
};
extern "C" int WINAPI _tWinMain(HINSTANCE /*hInstance*/, HINSTANCE hPrevInstance,LPTSTR /*lpCmdLine*/, int nShowCmd)
{
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
HANDLE logFile;
logFile = CreateFile("bstr_t_leak_LOG.txt", GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
_CrtSetReportFile(_CRT_WARN, logFile);
_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
_CrtSetReportFile(_CRT_ERROR, logFile);
_CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
_CrtSetReportFile(_CRT_ASSERT, logFile);
{
ATLASSERT(OleInitialize(0) == S_OK);
AtlAxWinInit();
{
CMyWindow w;
w.Create(0, 0, 0, WS_OVERLAPPEDWINDOW);
w.DestroyWindow();
}
AtlAxWinTerm();
OleUninitialize();
}
exit(0);
}
И в нем утечки нету!
Я в шоке.
Никаких статических переменных у себя кроме GUID (static const GUID LIBID_MyApp = ...) не имею. Что я не так делаю?
Здравствуйте, <Аноним>, Вы писали:
А>Есть приложение на ATL, которое показало утечку 2-х байт памяти (стандартными средствами crtdbg.h). Я вырезал из него все что можно. Осталось только это (сорри, отступы другой форум порезал):
Не бери близко к сердцу.
Во внутренностях классов некоторых библиотек используются статические члены (общие для всех экземпляров класса), которые размещаются при первом использовании и живут до завершения приложения. Создатели просто забивают на их удаление, так как при завершении процесса все его память освобождается по любому. (под Win32)
Конечно, если утечка растет — это другое дело.
... << RSDN@Home 1.1.3 stable >>
Здравствуйте, <Аноним>, Вы писали:
А>И в нем утечки нету!
А>Я в шоке.
А>
А>Никаких статических переменных у себя кроме GUID (static const GUID LIBID_MyApp = ...) не имею. Что я не так делаю?
Незнаю, назнаю. У меня есть утечка в обоих случаях. Но это не важно. Это ATL-ем выделяется память под ATOM, когда регится класс окна. Позже, уже после main`а она очищается. Так что никаких утечек реально нету.
А что бы ловить такие моменты, нужно делать так:
Detected memory leaks!
Dumping objects ->
{49} normal block at 0x00944D70, 2 bytes long.
Data: < > D8 C2
Object dump complete.
Выделенное — номер аллокации. Что бы остановиться при выделении этого куска памяти, нужно где-нить в начале программы написать:
_CrtSetBreakAlloc(49);
Когда будет выделятся блок с номером 49, дебагер предложит подебагить. Тут мы по стеку и смотрим, кто виноват и что делать.
Естественно, нужно постараться, что бы программа выделяла память в той же последовательности, что и при обнаружении лика, иначе номера сдвинутся.
Я — свихнувшееся сознание Джо.
А>>И в нем утечки нету!
А>>Я в шоке.
А>>
А>>Никаких статических переменных у себя кроме GUID (static const GUID LIBID_MyApp = ...) не имею. Что я не так делаю?
SJA>Незнаю, назнаю. У меня есть утечка в обоих случаях. Но это не важно. Это ATL-ем выделяется память под ATOM, когда регится класс окна. Позже, уже после main`а она очищается. Так что никаких утечек реально нету.
SJA>А что бы ловить такие моменты, нужно делать так:
SJA>Detected memory leaks!
SJA>Dumping objects ->
SJA>{49} normal block at 0x00944D70, 2 bytes long.
SJA>Data: < > D8 C2
SJA>Object dump complete.
SJA>Выделенное — номер аллокации. Что бы остановиться при выделении этого куска памяти, нужно где-нить в начале программы написать:
SJA>SJA>_CrtSetBreakAlloc(49);
SJA>
SJA>Когда будет выделятся блок с номером 49, дебагер предложит подебагить. Тут мы по стеку и смотрим, кто виноват и что делать.
SJA>Естественно, нужно постараться, что бы программа выделяла память в той же последовательности, что и при обнаружении лика, иначе номера сдвинутся.
Сенкс, я посмотрел, это действительно массив атомов в статической переменной _AtlWinModule. Так что это не утечка.