Untitled

posted in DruinkJournal
Published July 11, 2007
Advertisement
I've been digging around in a lot of low level code today, in order to make my memory manager tidier, faster and more fully featured.

The thing I'm up to my nuts in just now is the 10 memory leaks coming from STL code. Now, I used to have my memory manager as a static variable, but it's now malloc()'d and destroyed in an atexit() call. So, I figured that these allocations must be getting freed atexit(). Which is fair enough, except I discovered that the STL code is horrible. Now that might not come as much of a shock, but let me explain. This is all with the default STL that comes with VC2005 Professional, but I expect other VC2005 editions are the same.

  • Constructing a std::wstringstream causes the STL code to get the current locale.
  • Getting the current locale involes allocating a "facet" (Whatever that is).
  • The "facet" is allocated with operator new, and then stored in a static pointer inside the std::use_facet function (xlocal, line 468 for those of you playing along at home).
  • The allocated memory is then "registered" by a call to std::locale::facet::facet_register (locale0.cpp, line 172).
  • The facet_register function then calls ::_Atexit to register the _Fac_tidy function (Which is in local0.cpp, line 30).
  • ::_Atexit has a static global list (array) of 10 function pointers to various cleanup functions, and the function passed to it (_Fac_tidy) is added to that list.
  • There's a global variable (iosptrs.cpp, line 53) which is a structure with one member function in it - the destructor. This destructor calls all the functions in the array of function pointers.


    Now, that may seem reasonable I suppose. But what on earth is wrong with atexit()? What this really means is that there's no easy way for me to make sure my memory manager is destroyed after this global, so I don't pick up on these allocations. This only happens in an optimised build, not a debug one.

    So the question is - How do I (Or even can I?) register some code to be called after this global is destroyed. The order of construction of globals is undefined, and the order of destruction is the reverse of the order of construction. So that's also undefined.

    I really don't want to have special case code to ignore these allocations, since although there's "only" 10 of them, that's 10 string compares to do for every allocation (I use filename and line number from my stack walking function), and even if I do, there's nothing to stop me picking up on similar allocations later on.
    I can't access that global variable to call its destructor manually (Or do some hocus pocus), since it's a static variable.
    I can't change the STL code to get access to that variable, because then my code won't work on other machines, and it means I have to modify the STL on all the PCs I develop on (3, currently).

    The best I can think of is using some of the debug helper functions to look up the global by name, getting the address of it, and then destroying it (Well, the array of function pointers) myself in the destuctor of my memory allocator. But that still means that I've got special case code for this particular version of the STL.

    *scream*
  • Previous Entry Untitled
    Next Entry Untitled
    0 likes 5 comments

    Comments

    Ravuya
    I can provide md2 loading code for you. Lemme know when you want it.
    July 11, 2007 10:35 PM
    Evil Steve
    Quote:Original post by Ravuya
    I can provide md2 loading code for you. Lemme know when you want it.
    Thanks, but I already have MD2 loading code [smile]
    July 12, 2007 03:23 AM
    Moomin
    Quote:Original post by Evil Steve
    Quote:Original post by Ravuya
    I can provide md2 loading code for you. Lemme know when you want it.
    Thanks, but I already have MD2 loading code [smile]



    You didn't cross it off your list!!! :(
    July 12, 2007 11:20 AM
    Evil Steve
    Quote:Original post by Moomin
    Quote:Original post by Evil Steve
    Quote:Original post by Ravuya
    I can provide md2 loading code for you. Lemme know when you want it.
    Thanks, but I already have MD2 loading code [smile]



    You didn't cross it off your list!!! :(
    That's a good point. I'll rephrase that [smile] I have MD2 loading code from my old engine, which I intend to port to my new one (Since it's pretty generic as it is).
    July 12, 2007 12:45 PM
    Emmanuel Deloget
    Aren't globals created in the order of their appearance in the compilation unit? (if you have more compilation, their creation order follow the order in which the linker will find them).

    I'm too lazy this evening to check the standard, but that was my impression.

    Of course, that doesn't mean that it's going to help you :)
    July 16, 2007 01:38 PM
    You must log in to join the conversation.
    Don't have a GameDev.net account? Sign up!
    Advertisement
    Advertisement