开发者

memory leak: unable to break on a memory allocation number

开发者 https://www.devze.com 2023-01-04 14:28 出处:网络
I\'m trying to locate a memory leak issue. My project is an ATL based dialog project, that uses DirectShow and the standard library.

I'm trying to locate a memory leak issue.

My project is an ATL based dialog project, that uses DirectShow and the standard library.

I get a total of 45 memory leaks in my program, all 24 bytes each.

I've #define'd _CRTDBG_MAP_ALLOC etc in my stdafx.h, along with DEBUG_NEW to get the file and line numbers for each of the memory leaks.

However, no file line numbers are printed. The memory blocks are all "normal" blocks and look like this:

{180} normal block at 0x003E6008, 24 bytes long. Data: <  >  _>   > W   > A0 AE 3E 00 B0 5F 3E 00 A0 AE 3E 00 57 00 00 00 

I've tried adding the following line to the start of _tWinMain()

_CrtSetBreakAlloc(180);

in order to break on the allocation, but the debugger doesn't break at all.

Can anyone give me any insight into how I might track down the elusive memory leaks?

Finally, here's my _tWinMain() - I call _CrtDumpMemoryLeaks() just before exiting.

int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR lpstrCmdLine, int nCmdShow){
    _CrtSetBreakAlloc(180);

    HRESULT hRes = ::CoInitializeEx(NULL, COINIT_MULTITHREADED);
    ATLASSERT(SUCCEEDED(hRes));


    ::DefWindowProc(NULL, 0, 0, 0L);
    AtlInitCommonControls(ICC_BAR_CLASSES);

    //HINSTANCE开发者_StackOverflow社区 hInstRich = ::LoadLibrary(CRichEditCtrl::GetLibraryName());

    hRes = _Module.Init(NULL, hInstance);
    ATLASSERT(SUCCEEDED(hRes));

    int nRet = Run(lpstrCmdLine, nCmdShow);

    _Module.Term();
    ::CoUninitialize();

    _CrtDumpMemoryLeaks();

    return nRet;
}


Two suggestions.

Firstly, what gets constructed before main (or equivalent) starts gets destroyed after main finishes. Calling _CrtDumpMemoryLeaks at the end of main can give you false positives. (Or are they false negatives?) Global objects' destructors have yet to run, and atexit callbacks have yet to run, so the leak output will include allocations that have simply yet to be correctly freed.

(I suspect this is why your global objects are appearing to leak. There may well be nothing wrong with the code, and indeed it's quite possibly cleaning itself up properly -- the cleanup code has simply yet to run when _CrtDumpMemoryLeaks is being called.)

What you need to do instead is to direct the runtime library to call _CrtDumpMemoryLeaks for you, right at the end, after all the atexit callbacks and global object destructors have finished. Then you'll only see the genuine leaks. This snippet will do the trick. Stick at at the start of main:

_CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG)|_CRTDBG_LEAK_CHECK_DF);

Secondly, if the above reveals genuine leaks from stuff that runs before main, you can do a bit of trickery to get some of your own code running pretty much before anything else gets a look in. Then you can set _crtBreakAlloc before any allocations happen. Just pop the following code in a .cpp file of its own:

#include <crtdbg.h>

#ifdef _DEBUG

#pragma warning(disable:4074)//initializers put in compiler reserved initialization area
#pragma init_seg(compiler)//global objects in this file get constructed very early on

struct CrtBreakAllocSetter {
    CrtBreakAllocSetter() {
        _crtBreakAlloc=<allocation number of interest>;
    }
};

CrtBreakAllocSetter g_crtBreakAllocSetter;

#endif//_DEBUG

(I suspect that code in the compiler's init segment may well run before stdin and stdout and the like are initialised, and certainly before any global objects are constructed, so you may have difficulty doing anything more complicated than the above!)

(For what little it's worth, I'm of the opinion these days, and have been for some time now, that allocation before main starts is almost always a bad thing. Makes it hard to clean up after oneself, and difficult to keep track of what's going on. It's certainly convenient, but you always seem to end up paying for it later. That's advice that's much easier to hand out than it is to implement, though, particularly as part of a larger team.)


I had a couple of global variables (lookup tables that returned CString references to error messages) that I've removed from the program. As soon as I did - no memory leaks.

Thanks for your comments folks.

Interesting - I'll have to investigate a different way to implement error lookup.

I was doing something like:

CString sError = "error at line x: " + g_map.lookup(hrError);

The error map is implemented as an object that wraps access to an std::map, and it's destructor work fine. When I allocate this map object on the heap, and deallocate it, it reports no memory leaks. Maybe its the way I'm concatenating CString....

0

精彩评论

暂无评论...
验证码 换一张
取 消