Browsed by
Month: October 2011

Why _CrtDumpMemoryLeaks can make you think you’re leaking memory – but you’re not

Why _CrtDumpMemoryLeaks can make you think you’re leaking memory – but you’re not

I just spent an hour or two tracking down the last 16-byte memory leak in a project that I was working on. What it turned out to be was actually something EXPLICITLY cited in the Microsoft reference manual as having been fixed.  Yet it turned out not to be.

I had finished instrumenting my program for CRT memory reporting. CRT memory leak reporting is normally very handy as it tells you exactly what lines of code are the source of the leak, how many bytes, and dumps the data that’s leaking. All it requires is that you instrument your headers as described here <http://msdn.microsoft.com/en-us/library/x98tx3cf.aspx>

// this goes before ANY other includes in ALL your headers
#define _CRTDBG_MAP_ALLOC
#include <blah>
#include <blah>
...
 main()
{
    _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); // tells leak detector to dump report at any program exit
    _CrtSetBreakAlloc(18); // set breakpoint on a specific allocation number
}

With all this done you can run the program and then see the results of the report in the Visual studio output window when the program exits:

Detected memory leaks!
Dumping objects ->
C:PROGRAM FILESVISUAL STUDIOMyProjectsleaktestleaktest.cpp(20) : {18}
normal block at 0x00780E80, 64 bytes long.
Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
Object dump complete.

If you use the _CrtSetBreakAlloc() with the allocation number ({18}in this case), when the program starts up in debug mode the debugger will automatically stop on that allocation. You can then look at the call stack and get a great idea of whats leaking and why. Overall, it’s very handy and helped me track down all my leaks.

Well, the problem was that I fixed all the leaks but 2 in my particular program.  I reduced the code down until I was down to just main() that dumped the memory report and exited.   The problem was that it STILL reported a leak! I added a fake leak, and the very first allocation (that was leaking) in the program had a higher allocation number than the allocations that were supposedly leaking.  This implied quite strongly that the leak is happening BEFORE I actually even get into the program. How is that possible?

Well, there are a few things that get allocated for you before your program starts. Fixed-sized arrays, (int array[10];) string literals, and static variables are all objects are allocated on the stack (as opposed to the heap) are usually allocated at load time. When I looked at all the static allocations in my program, I saw this:

class Bar
{
    ...
private:
    static std::string m_name;
    static std::string m_value;
}

Do you see any problem?  I didn’t – at first. The problem is that std::string is a STL object that has a constructor.  Statics are usually allocated at load time. Which means their constructors are likely being called during load time BEFORE the main() is hit. We assume that the corresponding destructors are called after main exits. Apparently, the CRT memory tracking starts right as the program starts but is supposed to ignore any CRT allocations (ones made by the standard C libraries).  Apparently these static allocations by STL objects are captured.  Since we report leaks BEFORE we hit the program exit, we haven’t actually hit those ‘hidden’ destructors for those static strings yet.  Those allocations are still reported as active – and hence ‘leaked’.  I only caught this because I’d initialized those strings with string literals.  The leak dumped the memory and I recognized the strings. So a good way to test if this is happening to you is set your object data to something unique and make sure those unique values appear in the leak report memory dump.

Yet another clue is that the value of an uninitialized string consists of a number that appears to be a memory address (while the addresses change each run, other allocations in that run have roughly the same addresses), and a bunch of zeros. This likely corresponds to a pointer to the character buffer, and an int that indicates size. This is further confirmed by the fact the leaks are 8 bytes each in x86 build, and 16 bytes on a x64 build. This corresponds to the sizeof(int)+sizeof(void*) sizes on the respective builds.

Solution:
The solution is to ignore what is (likely) a false report, or change the static std::string objects to non-static or static std::string* pointers. Then make an appropriate initializer/destructor that creates/destroys those string objects. This means the memory is allocated/deallocated on the heap in the scope of the program run. The other thing you do is file a bug with Microsoft and put a few comments on the documentation website that indicates the statics are still leaking and they haven’t really fixed it yet. 🙂

Links:
MS article about CRT memory debug operations that says this bug had been fixed (but it has not as of VS2012)

http://msdn.microsoft.com/en-us/library/x98tx3cf.aspx

When the less-obvious solution is best

When the less-obvious solution is best

Sometimes more really isn’t the answer.

Case and point – dishes at your house.  I saw this picture and college days of yore flooded back:

At one bachelor flat I lived at – our sink often looked like this.  We had 4 guys living in one house, and dishes weren’t a high-priority item.  So, they tended to pile up and then nobody seemed to remember who dirtied what and an endless cycle of blame and avoidance resulted.

The solution: throw out all the extra dishes.  Instead, there was *exactly 1* set of silverware, plate, and glass for each person.  Further, each one was color-coded.  Red plate/cup/silverware was Bob’s.  Green was Fred’s, etc.  That meant if you wanted to eat something, then you had to have washed your stuff to do so.  It also meant if you left your dirty dishes around – the culprit was immediately identifiable.  The first benefit was that with only 4 plates in the house, a ‘pile’ of them never got very big.  The second was that very quickly the innocents were vindicated, and slobs were identified. (We still had a full set of ‘nice’ dishes for when people came over for a dinner – but they were in a separate cupboard.  Anyone seen using those individually would be berated furiously).   The system worked like a charm and there was nary an argument about dishes for the rest of the time I lived there.

I think this is a corollary to many a home-owner’s observation that your possessions naturally expand to fit the space you have.   Or maybe Apple’s design philosophy that sometimes its the limitations you put on the usage of the device that actually allow easier and higher functionality.

Great time at the beach

Great time at the beach

I hadn’t taken much vacation this year (3 days to be exact), and had been grinding on a lot of code the last few months.  So, I dug through our list of corporate discounts and found a great place on the Oregon coast I could stay at for cheap.  So, I took 2 days off and went to Pacific City, OR and got this great view from my room every night.

I feel I got quite lucky because the weather at the coast isn’t usually very clear in the fall – but I got two near-perfect days.  Guess someone was looking out for me.  🙂