Jump to content
  • Advertisement
Sign in to follow this  
Evil Steve

Unity Critique my memory tracker

This topic is 4202 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Until we get a Peer Review Forum, this can go here [smile] Anyway, I've written a memory manager which is pretty unobtrusive. It doesn't require macro hackery like MMGR, it tracks STL allocations, it works in x64, and is thread safe. And it gives the file, line number and function name of allocations. On the down side, it only works in debug builds, only on Windows, it's probably slow, and I don't like the stack walking code very much, it seems a bit hacky. It doesn't currently have any support for breaking on allocations since I haven't needed that support, but it should be easy enough to understand and modify. So here's the source code: PMemory.h, PMemory.cpp. The source is a little long to post here on a [ source ] tag, but the links are straight to the .cpp and .h files. It won't compile straight off, there's 3 changes you'll need to make.
  1. #define USE_MMGR in your peoject settings, or remove all references to USE_MMGR
  2. Remove the #include of EMemory.h
  3. Remove the Assert() calls, or implement your own Assert() macro
The stack walking code "works on my machine", you might need to change the number of frames to walk on your own machines. Anyway, I'd be glad to hear any comments / suggestions / insults etc [smile] Cheers, Steve

Share this post


Link to post
Share on other sites
Advertisement
I would suggest that before you write your own memory management tools, you get familiar with what the development environment you're using already provides. If you're using DevStudio on Windows, then take a look at these articles about the debug heap. There's a huge amount of information available about memory usage. From personal experiance, I've found I've never needed any additional memory diagnostics to find problems.

Skizz

Share this post


Link to post
Share on other sites
Quote:
Original post by Skizz
I would suggest that before you write your own memory management tools, you get familiar with what the development environment you're using already provides. If you're using DevStudio on Windows, then take a look at these articles about the debug heap. There's a huge amount of information available about memory usage. From personal experiance, I've found I've never needed any additional memory diagnostics to find problems.

Skizz
I've skimmed over that before, although the last time I tried it, it didn't tell me the file:line or function of the allocation. Another thing you could do with my allocator, is store a full call stack, or at least several frames, that would allow you to more precisely find where leaks are comming from (E.g. STL containers).

Share this post


Link to post
Share on other sites
Although file::line information might be useful to find the location of a leak, for example, in many instances it's not enough:

for (int i = 0; i < 100000 ; ++i)
{
// do something that allocates memory
}

How would file::line help if iteration 45623 leaks memory but the rest don't? Using the _CrtSetDbgFlag function to set the _CRTDBG_LEAK_CHECK_DF flag produces a list of all the leaky memory in DevStudio's output window when the program exits. The important field here is the allocation number (in '{}'s IIRC). You can then use _CrtSetBreakAlloc to specify a break point for that allocation request. So, your code would be:

void main (args)
{
// set _CRTDBG_LEAK_CHECK_DF
if (there's an argument)
{
_CrtSetBreakAlloc (atoi (arg));
}

// rest of program
}

and you would do the following:

1) run program
2) if no leaks, end
3) get allocation number
4) run program with allocation number
5) program breaks to debugger when allocation made

Now, this is far better than just file::line information as it not only gives you the location but the context as well and the ability to debug and poke around the system.

Skizz

Share this post


Link to post
Share on other sites
Breaking on an allocation ID is trivial to do, in fact the code is already there in the .cpp, there's just no function to set the break on alloc number [smile]
Breaking on an alloc ID only helps if your program allocates memory the exact same way each run. Admittedly, you'd try to do this anyway if you were tracking a memory leak, but there are many cases where it's not possible, such as the leak occuring at some allocation during the game. You'd have to run the game in the exact same way (including resetting all RNGs to the same value and ensuring the user input happens on the same frames, etc) to have the alloc ID alone be of any use.

Every other memory manager I've looked at (Although I haven't looked at many) either doesn't give you file and line information, or uses macro hackery to get you it, which breaks in some cases (E.g. MMGR using member operator new).

Share this post


Link to post
Share on other sites
You're right, allocation ID does require consistent memory allocation and that is the main drawback to that method.

Just out of interest, what's the overhead of walking the stack and getting the caller location? It has to be said that the macro method for getting allocation location has very minimal overhead and is more portable (if that's important) but does suffer from having to code differently (i.e. not use 'new' directly).

Skizz

Share this post


Link to post
Share on other sites
  • __PMEMORY_H__. Reserved symbol. Evil (Steve).

  • You seem to be using std namespace symbols in headers without namespace prefixes. I hope you don't have a using namespace std; in a header. That would just be Evil (Steve).

  • Hungarian Notation. Ugh.

  • Varargs. Ugh. Yes, I realise you're using it to avoid recursive calls to the memory manager, but still Ugh.

  • Your operator new([])s don't follow the standard on allocation failure. You should loop, trying to allocate each time and, if failing to allocate either call the currently installed new_handler (if there is one) and loop again or throw std::bad_alloc if there is no currently installed new_handler.

  • I'm pretty sure local static variables are not thread-safe.

  • Your returned memory is not guaranteed to satisfy alignment requirements.

  • It's possible that IMAGEHLP_LINE64::FileName is a pointer into the executables debug symbols, in which case you can just store the pointer rather than keeping an oversized buffer and copying the string yourself.
All in all, it looks pretty good. I've tried writing a similar implementation myself, but walking the stack manually (and hooking in to gcc's debug symbols). It works fairly well, although these days I manually allocate memory so infrequently I find a full-blown memory manager to be a bit over-the-top.

Σnigma

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!