Как игнорировать ложноположительные утечки памяти из _CrtDumpMemoryLeaks?

Кажется, что когда есть статические объекты, _CrtDumpMemoryLeaks возвращает ложное положительное утверждение о том, что это утечка памяти. Я знаю, что это происходит потому, что они не уничтожаются до тех пор, пока функция main() (или WinMain) не будет уничтожена. Но есть ли способ избежать этого? Я использую VS2008.

Ответ 1

Я обнаружил, что если вы скажете ему автоматически проверять память после завершения программы, она позволяет учитывать все статические объекты. Я использовал log4cxx и boost, которые делают много распределений в статических блоках, это фиксировало мои "ложные срабатывания"...

Добавьте следующую строку вместо вызова _CrtDumpMemoryLeaks, где-то в начале main():

_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );

Дополнительные сведения об использовании и макросах см. в статье MSDN:

http://msdn.microsoft.com/en-us/library/5at7yxcs (v = vs .71).aspx

Ответ 2

Не прямое решение, но в целом я счел целесообразным переместить как можно больше возможностей из статического времени инициализации. Обычно это приводит к головным болям (порядок инициализации, порядок инициализации и т.д.).

Если это слишком сложно, вы можете вызвать _CrtMemCheckpoint (http://msdn.microsoft.com/en-us/library/h3z85t43%28VS.80%29.aspx) в начале main() и _CrtMemDumpAllObjectsSince в конце.

Ответ 3

1) Вы сказали:

Кажется, что когда есть статические объекты, _CrtDumpMemoryLeaks возвращает ложное положительное утверждение о том, что это утечка памяти.

Я не думаю, что это правильно. EDIT: Статические объекты не создаются в куче. END EDIT: _CrtDumpMemoryLeaks охватывает только кучу памяти crt. Поэтому эти объекты не должны возвращать ложные срабатывания. Однако, другое дело, если статические переменные являются объектами, которые сами хранят некоторую кучную память (если, например, они динамически создают объекты-члены с помощью operator new()).

2) Рассмотрим, используя _CRTDBG_LEAK_CHECK_DF, чтобы активировать проверку утечки памяти в конце выполнения программы (это описано здесь: http://msdn.microsoft.com/en-us/library/d41t22sb(VS.80).aspx). Я полагаю, что проверка утечки памяти выполняется даже после завершения статических переменных.

Ответ 4

Старый вопрос, но у меня есть ответ. Я могу разбить отчет на ложные срабатывания и реальные утечки памяти. В своей основной функции я инициализирую отладку памяти и вырабатываю реальную утечку памяти в самом начале моего приложения (никогда не удаляйте pcDynamicHeapStart):

int main()
{   
   _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
   char* pcDynamicHeapStart = new char[ 17u ];
   strcpy_s( pcDynamicHeapStart, 17u, "DynamicHeapStart" );

   ...

После того, как моя заявка закончена, отчет содержит

Detected memory leaks!
Dumping objects ->
{15554} normal block at 0x00000000009CB7C0, 80 bytes long.
Data: <                > DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD
{14006} normal block at 0x00000000009CB360, 17 bytes long.
Data: <DynamicHeapStart> 44 79 6E 61 6D 69 63 48 65 61 70 53 74 61 72 74 
{13998} normal block at 0x00000000009BF4B0, 32 bytes long.
Data: < ^              > E0 5E 9B 00 00 00 00 00 F0 7F 9C 00 00 00 00 00 
{13997} normal block at 0x00000000009CA4B0, 8 bytes long.
Data: <        > 14 00 00 00 00 00 00 00 
{13982} normal block at 0x00000000009CB7C0, 16 bytes long.
Data: <   @            > D0 DD D6 40 01 00 00 00 90 08 9C 00 00 00 00 00

...

Object dump complete.

Теперь посмотрите на строку "Данные: < DynamicHeapStart > 44 79 6E 61 6D 69 63 48 65 61 70 53 74 61 72 74".

Все нижеуказанные утечки являются ложными срабатываниями, все вышеперечисленные являются настоящими утечками. Ложные срабатывания не означают, что утечки нет (это может быть статически связанная библиотека, которая выделяет кучу при запуске и никогда не освобождает ее), но вы не можете устранить утечку и это вообще не проблема.

С тех пор как я изобрел этот подход, у меня больше не было утечек приложений. Я предоставляю это здесь и надеюсь, что это поможет другим разработчикам получить стабильные приложения.

Ответ 5

Можете ли вы сделать снимок выделенных в настоящее время объектов каждый раз, когда вы хотите получить список? Если это так, вы можете удалить первоначально выделенные объекты из списка, когда ищете утечки, которые возникают при работе. В прошлом я использовал это, чтобы найти инкрементные утечки.

Другим решением может быть сортировка утечек и рассмотрение только дубликатов для одной и той же строки кода. Это должно исключать статические переменные утечки.

Jacob

Ответ 6

Ach. Если вы уверены, что _CrtDumpMemoryLeaks() лежит, то вы, вероятно, правы. Большинство предполагаемых утечек памяти, которые, как я вижу, не соответствуют вызовам _CrtDumpMemoryLeaks(). Я полностью согласен со следующим: _CrtDumpMemoryLeaks() сбрасывает все открытые дескрипторы. Но у вашей программы, вероятно, уже есть открытые дескрипторы, поэтому обязательно вызывайте _CrtDumpMemoryLeaks() только тогда, когда все дескрипторы выпущены. Подробнее см. http://www.scottleckie.com/2010/08/_crtdumpmemoryleaks-and-related-fun/.

Ответ 7

Я могу порекомендовать Visual Leak Detector (он бесплатный), а не использовать вещи, встроенные в VS. Моя проблема заключалась в использовании _CrtDumpMemoryLeaks с библиотекой с открытым исходным кодом, которая создала 990 строк вывода, насколько я могу судить, со всеми ложными срабатываниями, а также с некоторыми улучшениями. VLD проигнорировал их и правильно сообщил о некоторых утечках, которые я добавил для тестирования, в том числе в нативной DLL, вызываемой из С#.