Проблема с отловом утечек памяти
От: Trapper  
Дата: 18.08.04 11:25
Оценка:
Всем привет.

Прочитал статью здесь
Автор(ы): Александр Шаргин
Дата: 27.01.2002


Там предлагается использовать конструкцию

#ifdef _DEBUG
#ifdef _CRTDBG_MAP_ALLOC
#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
#endif /* _CRTDBG_MAP_ALLOC */
#endif /* _DEBUG */


После чего есть предупреждение:
Глобальная замена оператора new в коде программы обычно является безопасной операцией. Но если в области действия приведённого выше макроса окажется класс, реализующий собственную версию оператора new, Visual C++ откажется его компилировать и выдаст множество странных ошибок. Будьте внимательны, чтобы не допустить такой ситуации.

Вот собственно с этим у меня проблемы. У меня приложение, написанное на архитектуре документ/вид. В исходниках MFC переодически объявляются их собстенные варианты new, так что при добавлении моего дебажного new программа перестаёт компилиться. Что можно с этим сделать?
Trapper
Re: Проблема с отловом утечек памяти
От: IamLexa  
Дата: 18.08.04 12:32
Оценка:
Здравствуйте, Trapper, Вы писали:

T>Всем привет.


T>Прочитал статью здесь
Автор(ы): Александр Шаргин
Дата: 27.01.2002


T>Там предлагается использовать конструкцию


T>
T>#ifdef _DEBUG
T>#ifdef _CRTDBG_MAP_ALLOC
T>#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
T>#endif /* _CRTDBG_MAP_ALLOC */
T>#endif /* _DEBUG */
T>


T>После чего есть предупреждение:

T>Глобальная замена оператора new в коде программы обычно является безопасной операцией. Но если в области действия приведённого выше макроса окажется класс, реализующий собственную версию оператора new, Visual C++ откажется его компилировать и выдаст множество странных ошибок. Будьте внимательны, чтобы не допустить такой ситуации.

T>Вот собственно с этим у меня проблемы. У меня приложение, написанное на архитектуре документ/вид. В исходниках MFC переодически объявляются их собстенные варианты new, так что при добавлении моего дебажного new программа перестаёт компилиться. Что можно с этим сделать?


я так понимаю, что ты должен был тока определить макрос _CRTDBG_MAP_ALLOC
(проще всего это сделать в настройках проекта). и подключил файл <ctrdbg.h>?
ты все это сделал и посыпались ошибки?
Re[2]: Проблема с отловом утечек памяти
От: Trapper  
Дата: 18.08.04 12:41
Оценка:
IL>я так понимаю, что ты должен был тока определить макрос _CRTDBG_MAP_ALLOC
IL>(проще всего это сделать в настройках проекта). и подключил файл <ctrdbg.h>?
IL>ты все это сделал и посыпались ошибки?


Да, все необходимые действия я уже сделал. Более того, я выяснил, что не компилятся классы, которые объявлены с IMPLEMENT_DYNCREATE. Остальные (даже MFC — шные) компилятся без проблем, и что самое главное, правильно показывают, где происходят утечки памяти.
Trapper
Re[3]: Проблема с отловом утечек памяти
От: IamLexa  
Дата: 18.08.04 12:53
Оценка:
Здравствуйте, Trapper, Вы писали:

IL>>я так понимаю, что ты должен был тока определить макрос _CRTDBG_MAP_ALLOC

IL>>(проще всего это сделать в настройках проекта). и подключил файл <ctrdbg.h>?
IL>>ты все это сделал и посыпались ошибки?


T>Да, все необходимые действия я уже сделал. Более того, я выяснил, что не компилятся классы, которые объявлены с IMPLEMENT_DYNCREATE. Остальные (даже MFC — шные) компилятся без проблем, и что самое главное, правильно показывают, где происходят утечки памяти.


а какие ошибки получаешь? можешь прислать кусок кода, который не компилится?
Re[4]: Проблема с отловом утечек памяти
От: Trapper  
Дата: 18.08.04 13:13
Оценка:
IL>а какие ошибки получаешь? можешь прислать кусок кода, который не компилится?

Не вопрос!



#ifdef _DEBUG
#ifdef _CRTDBG_MAP_ALLOC
#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
#endif 
#endif 


// CMyDoc

IMPLEMENT_DYNCREATE(CMyDoc, CDocument)


Ошибка в строчке с IMPLEMENT_DYNCREATE
error C2661: 'CObject::operator new' : no overloaded function takes 4 parameters

По всей видимости, это из — за того, что в IMPLEMENT_DYNCREATE используется оператор new, который определён где — то раньше, и принимает другие параметры.
Вопрос в том, что с этим всем делать?
Trapper
Re[5]: Проблема с отловом утечек памяти
От: IamLexa  
Дата: 18.08.04 13:26
Оценка:
Здравствуйте, Trapper, Вы писали:

IL>>а какие ошибки получаешь? можешь прислать кусок кода, который не компилится?


T>Не вопрос!



T>

T>#ifdef _DEBUG
T>#ifdef _CRTDBG_MAP_ALLOC
T>#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
T>#endif 
T>#endif 


T>// CMyDoc

T>IMPLEMENT_DYNCREATE(CMyDoc, CDocument)

T>


T>Ошибка в строчке с IMPLEMENT_DYNCREATE

T>error C2661: 'CObject::operator new' : no overloaded function takes 4 parameters

T>По всей видимости, это из — за того, что в IMPLEMENT_DYNCREATE используется оператор new, который определён где — то раньше, и принимает другие параметры.

T>Вопрос в том, что с этим всем делать?

я так понял, что ты добавил
#ifdef _DEBUG
#ifdef _CRTDBG_MAP_ALLOC
#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
#endif 
#endif

в h-файл. этого делать не надо. просто добавь в св-вах проекта на вкладке C/C++/Preprocessor в "Preprocessor Definitions" _CRTDBG_MAP_ALLOC
Re: Проблема с отловом утечек памяти
От: Odi$$ey Россия http://malgarr.blogspot.com/
Дата: 18.08.04 13:35
Оценка:
Здравствуйте, Trapper, Вы писали:

T>Вот собственно с этим у меня проблемы. У меня приложение, написанное на архитектуре документ/вид. В исходниках MFC


зачем это все, если используешь MFC, в debug-вариантах MFC проектов, по крайней мере созданных мастером, утечки памяти уже отслеживаются
Re[6]: Проблема с отловом утечек памяти
От: Trapper  
Дата: 19.08.04 11:24
Оценка:
IL>я так понял, что ты добавил
IL>
IL>#ifdef _DEBUG
IL>#ifdef _CRTDBG_MAP_ALLOC
IL>#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
IL>#endif 
IL>#endif 
IL>

IL>в h-файл. этого делать не надо. просто добавь в св-вах проекта на вкладке C/C++/Preprocessor в "Preprocessor Definitions" _CRTDBG_MAP_ALLOC


Ты меня правильно понял
Но добавлять эту директиву в проект нельзя — проект сразу перестаёт компилиться
Trapper
Re[7]: Проблема с отловом утечек памяти
От: IamLexa  
Дата: 19.08.04 13:06
Оценка:
Здравствуйте, Trapper, Вы писали:

IL>>я так понял, что ты добавил

IL>>
IL>>#ifdef _DEBUG
IL>>#ifdef _CRTDBG_MAP_ALLOC
IL>>#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
IL>>#endif 
IL>>#endif 
IL>>

IL>>в h-файл. этого делать не надо. просто добавь в св-вах проекта на вкладке C/C++/Preprocessor в "Preprocessor Definitions" _CRTDBG_MAP_ALLOC


T>Ты меня правильно понял

T>Но добавлять эту директиву в проект нельзя — проект сразу перестаёт компилиться

вообще-то странно. а не пробовал просто позвать
 _CrtSetDbgFlag (_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);

из DllMain или (Win)Main или чего там вместо них в MFC?
по идее при завершении программы должена быть ввыведена инф-ция о мемори-ликах.
может не будет номеров строк и файлов -- можно изловчиться и без этого обойтись.
Re[8]: Проблема с отловом утечек памяти
От: Trapper  
Дата: 19.08.04 13:49
Оценка:
IL>вообще-то странно. а не пробовал просто позвать
IL>
IL> _CrtSetDbgFlag (_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
IL>

IL>из DllMain или (Win)Main или чего там вместо них в MFC?
IL>по идее при завершении программы должена быть ввыведена инф-ция о мемори-ликах.
IL>может не будет номеров строк и файлов -- можно изловчиться и без этого обойтись.


Ты будешь долго смеяться, но я вызываю эту функцию при старте приложения в CMyApp::CMyApp()
Определённый дамп я получаю в окно Output, но без информации о номере строки и имени файла. Проект большой, гадать не хочется
Trapper
Re: Проблема с отловом утечек памяти
От: Burz  
Дата: 19.08.04 14:00
Оценка:
Здравствуйте, Trapper, Вы писали:

T>Всем привет.


T>Прочитал статью здесь
Автор(ы): Александр Шаргин
Дата: 27.01.2002


T>Там предлагается использовать конструкцию


T>
T>#ifdef _DEBUG
T>#ifdef _CRTDBG_MAP_ALLOC
T>#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
T>#endif /* _CRTDBG_MAP_ALLOC */
T>#endif /* _DEBUG */
T>


В MFC уже есть реализация new. Что-то типа:
>#define new(size_t s) new(s, _NORMAL_BLOCK, __FILE__, __LINE__)


Поэтому ничего кроме _CRTDBG_MAP_ALLOC добавлять не надо.
Re[9]: Проблема с отловом утечек памяти
От: IamLexa  
Дата: 19.08.04 14:14
Оценка:
Здравствуйте, Trapper, Вы писали:

IL>>вообще-то странно. а не пробовал просто позвать

IL>>
IL>> _CrtSetDbgFlag (_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
IL>>

IL>>из DllMain или (Win)Main или чего там вместо них в MFC?
IL>>по идее при завершении программы должена быть ввыведена инф-ция о мемори-ликах.
IL>>может не будет номеров строк и файлов -- можно изловчиться и без этого обойтись.


T>Ты будешь долго смеяться, но я вызываю эту функцию при старте приложения в CMyApp::CMyApp()

T>Определённый дамп я получаю в окно Output, но без информации о номере строки и имени файла. Проект большой, гадать не хочется

а чего гадать? номер неосвобожденного блока тебе в логе пишут.
поэтому можно поставить условный breakpoint в файле dbgheap.c в функции _heap_alloc_dbg:

431:       pHead->pBlockHeaderNext = _pFirstBlock;
432:       pHead->pBlockHeaderPrev = NULL;
433:       pHead->szFileName = (char *)szFileName;
434:       pHead->nLine = nLine;
435:       pHead->nDataSize = nSize;
436:       pHead->nBlockUse = nBlockUse;
437:       pHead->lRequest = lRequest; // <--- здесь! lRequest -- это номер блока


условный breakpoint типа "lRequest = 777".
Поэтому после запуска программы останавливаешься в момент выделения этого блока -- а потом выясняешь, почему ты его не удалил.

PS. dbgheap.cpp лежит в каталоге Visual Studio Dir\Vc7\crt\src\dbgheap.c
Re[2]: Проблема с отловом утечек памяти
От: Trapper  
Дата: 20.08.04 06:27
Оценка:
В общем да, может я действительно фигнёй занимаюсь
Trapper
Re[10]: Проблема с отловом утечек памяти
От: Trapper  
Дата: 20.08.04 07:35
Оценка:
IL>а чего гадать? номер неосвобожденного блока тебе в логе пишут.
IL>поэтому можно поставить условный breakpoint в файле dbgheap.c в функции _heap_alloc_dbg:

IL>
IL>431:       pHead->pBlockHeaderNext = _pFirstBlock;
IL>432:       pHead->pBlockHeaderPrev = NULL;
IL>433:       pHead->szFileName = (char *)szFileName;
IL>434:       pHead->nLine = nLine;
IL>435:       pHead->nDataSize = nSize;
IL>436:       pHead->nBlockUse = nBlockUse;
IL>437:       pHead->lRequest = lRequest; // <--- здесь! lRequest -- это номер блока
IL>


IL>условный breakpoint типа "lRequest = 777".

IL>Поэтому после запуска программы останавливаешься в момент выделения этого блока -- а потом выясняешь, почему ты его не удалил.

IL>PS. dbgheap.cpp лежит в каталоге Visual Studio Dir\Vc7\crt\src\dbgheap.c


Спасибо, не знал про такой способ!
Сижу в дебагере, вернусь не скоро
Trapper
Re[10]: Проблема с отловом утечек памяти
От: mentor Россия  
Дата: 20.08.04 17:59
Оценка:
Здравствуйте, IamLexa, Вы писали:

IL>а чего гадать? номер неосвобожденного блока тебе в логе пишут.

IL>поэтому можно поставить условный breakpoint в файле dbgheap.c в функции _heap_alloc_dbg:

IL>
IL>431:       pHead->pBlockHeaderNext = _pFirstBlock;
IL>432:       pHead->pBlockHeaderPrev = NULL;
IL>433:       pHead->szFileName = (char *)szFileName;
IL>434:       pHead->nLine = nLine;
IL>435:       pHead->nDataSize = nSize;
IL>436:       pHead->nBlockUse = nBlockUse;
IL>437:       pHead->lRequest = lRequest; // <--- здесь! lRequest -- это номер блока
IL>


IL>условный breakpoint типа "lRequest = 777".

IL>Поэтому после запуска программы останавливаешься в момент выделения этого блока -- а потом выясняешь, почему ты его не удалил.

IL>PS. dbgheap.cpp лежит в каталоге Visual Studio Dir\Vc7\crt\src\dbgheap.c


А можно глупый вопрос, как туда бряк поставить, вроде в проект его не добавить. Разьясните поподробней или дайте плз ссылочку.
Re[11]: Проблема с отловом утечек памяти
От: IamLexa  
Дата: 23.08.04 05:53
Оценка:
Здравствуйте, mentor, Вы писали:

IL>>PS. dbgheap.cpp лежит в каталоге Visual Studio Dir\Vc7\crt\src\dbgheap.c


M>А можно глупый вопрос, как туда бряк поставить, вроде в проект его не добавить. Разьясните поподробней или дайте плз ссылочку.


Если ты используешь debug-версию C runtime, то этот файл уже в твоем проекте (в libc.lib, libcmt.lib ...)
Так что открывай его, ставь бряк и пользуйся.
Re: Проблема с отловом утечек памяти
От: Аноним  
Дата: 23.08.04 07:55
Оценка: +1
Здравствуйте, Trapper, Вы писали:

T>Всем привет.


T>Прочитал статью здесь
Автор(ы): Александр Шаргин
Дата: 27.01.2002


T>Там предлагается использовать конструкцию


T>
T>#ifdef _DEBUG
T>#ifdef _CRTDBG_MAP_ALLOC
T>#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
T>#endif /* _CRTDBG_MAP_ALLOC */
T>#endif /* _DEBUG */
T>


T>После чего есть предупреждение:

T>Глобальная замена оператора new в коде программы обычно является безопасной операцией. Но если в области действия приведённого выше макроса окажется класс, реализующий собственную версию оператора new, Visual C++ откажется его компилировать и выдаст множество странных ошибок. Будьте внимательны, чтобы не допустить такой ситуации.

T>Вот собственно с этим у меня проблемы. У меня приложение, написанное на архитектуре документ/вид. В исходниках MFC переодически объявляются их собстенные варианты new, так что при добавлении моего дебажного new программа перестаёт компилиться. Что можно с этим сделать?


Уважаемый, та статья была написана для проектов, которые не используют MFC. У MFC уже все это есть. Когда вы генерируете любой default MFC project, в код каждого CPP file (исключая stdafx.cpp file) CPP вставляется такая конструкция:
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

Этот код и обеспечивает переопределение оператора new и отлов memory leak.
Re[12]: Проблема с отловом утечек памяти
От: mentor Россия  
Дата: 23.08.04 08:08
Оценка:
Здравствуйте, IamLexa, Вы писали:

M>>А можно глупый вопрос, как туда бряк поставить, вроде в проект его не добавить. Разьясните поподробней или дайте плз ссылочку.


IL>Если ты используешь debug-версию C runtime, то этот файл уже в твоем проекте (в libc.lib, libcmt.lib ...)

IL>Так что открывай его, ставь бряк и пользуйся.

А если я открываю его, ставлю бряк, а он мне говорит, что бряк будет disabled то это значит, что я не debug-версию использую или что не так файл открываю?
Re[2]: Проблема с отловом утечек памяти
От: Trapper  
Дата: 23.08.04 08:27
Оценка:
А>Уважаемый, та статья была написана для проектов, которые не используют MFC. У MFC уже все это есть. Когда вы генерируете любой default MFC project, в код каждого CPP file (исключая stdafx.cpp file) CPP вставляется такая конструкция:
А>
А>#ifdef _DEBUG
А>#define new DEBUG_NEW
А>#undef THIS_FILE
А>static char THIS_FILE[] = __FILE__;
А>#endif
А>

А>Этот код и обеспечивает переопределение оператора new и отлов memory leak.


Йес, это я уже понял
Trapper
Re[13]: Проблема с отловом утечек памяти
От: Trapper  
Дата: 23.08.04 08:30
Оценка:
Здравствуйте, mentor, Вы писали:

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


M>>>А можно глупый вопрос, как туда бряк поставить, вроде в проект его не добавить. Разьясните поподробней или дайте плз ссылочку.


IL>>Если ты используешь debug-версию C runtime, то этот файл уже в твоем проекте (в libc.lib, libcmt.lib ...)

IL>>Так что открывай его, ставь бряк и пользуйся.

M>А если я открываю его, ставлю бряк, а он мне говорит, что бряк будет disabled то это значит, что я не debug-версию использую или что не так файл открываю?


Хм.. странно. У меня вообще такого сообщения нет. Даже в релизной версии брекпоинт ставится нормально.
Trapper
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.