Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 904059
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 15, 20262026-05-15T15:59:18+00:00 2026-05-15T15:59:18+00:00

I’m writing a memory tracking system and the only problem I’ve actually run into

  • 0

I’m writing a memory tracking system and the only problem I’ve actually run into is that when the application exits, any static/global classes that didn’t allocate in their constructor, but are deallocating in their deconstructor are deallocating after my memory tracking stuff has reported the allocated data as a leak.

As far as I can tell, the only way for me to properly solve this would be to either force the placement of the memory tracker’s _atexit callback at the head of the stack (so that it is called last) or have it execute after the entire _atexit stack has been unwound. Is it actually possible to implement either of these solutions, or is there another solution that I have overlooked.

Edit:
I’m working on/developing for Windows XP and compiling with VS2005.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-15T15:59:19+00:00Added an answer on May 15, 2026 at 3:59 pm

    I’ve finally figured out how to do this under Windows/Visual Studio. Looking through the crt startup function again (specifically where it calls the initializers for globals), I noticed that it was simply running “function pointers” that were contained between certain segments. So with just a little bit of knowledge on how the linker works, I came up with this:

    #include <iostream>
    using std::cout;
    using std::endl;
    
    // Typedef for the function pointer
    typedef void (*_PVFV)(void);
    
    // Our various functions/classes that are going to log the application startup/exit
    struct TestClass
    {
        int m_instanceID;
    
        TestClass(int instanceID) : m_instanceID(instanceID) { cout << "  Creating TestClass: " << m_instanceID << endl; }
        ~TestClass() {cout << "  Destroying TestClass: " << m_instanceID << endl; }
    };
    static int InitInt(const char *ptr) { cout << "  Initializing Variable: " << ptr << endl; return 42; }
    static void LastOnExitFunc() { puts("Called " __FUNCTION__ "();"); }
    static void CInit() { puts("Called " __FUNCTION__ "();"); atexit(&LastOnExitFunc); }
    static void CppInit() { puts("Called " __FUNCTION__ "();"); }
    
    // our variables to be intialized
    extern "C" { static int testCVar1 = InitInt("testCVar1"); }
    static TestClass testClassInstance1(1);
    static int testCppVar1 = InitInt("testCppVar1");
    
    // Define where our segment names
    #define SEGMENT_C_INIT      ".CRT$XIM"
    #define SEGMENT_CPP_INIT    ".CRT$XCM"
    
    // Build our various function tables and insert them into the correct segments.
    #pragma data_seg(SEGMENT_C_INIT)
    #pragma data_seg(SEGMENT_CPP_INIT)
    #pragma data_seg() // Switch back to the default segment
    
    // Call create our call function pointer arrays and place them in the segments created above
    #define SEG_ALLOCATE(SEGMENT)   __declspec(allocate(SEGMENT))
    SEG_ALLOCATE(SEGMENT_C_INIT) _PVFV c_init_funcs[] = { &CInit };
    SEG_ALLOCATE(SEGMENT_CPP_INIT) _PVFV cpp_init_funcs[] = { &CppInit };
    
    
    // Some more variables just to show that declaration order isn't affecting anything
    extern "C" { static int testCVar2 = InitInt("testCVar2"); }
    static TestClass testClassInstance2(2);
    static int testCppVar2 = InitInt("testCppVar2");
    
    
    // Main function which prints itself just so we can see where the app actually enters
    void main()
    {
        cout << "    Entered Main()!" << endl;
    }
    

    which outputs:

    Called CInit();
    Called CppInit();
      Initializing Variable: testCVar1
      Creating TestClass: 1
      Initializing Variable: testCppVar1
      Initializing Variable: testCVar2
      Creating TestClass: 2
      Initializing Variable: testCppVar2
        Entered Main()!
      Destroying TestClass: 2
      Destroying TestClass: 1
    Called LastOnExitFunc();
    

    This works due to the way MS have written their runtime library. Basically, they’ve setup the following variables in the data segments:

    (although this info is copyright I believe this is fair use as it doesn’t devalue the original and IS only here for reference)

    extern _CRTALLOC(".CRT$XIA") _PIFV __xi_a[];
    extern _CRTALLOC(".CRT$XIZ") _PIFV __xi_z[];    /* C initializers */
    extern _CRTALLOC(".CRT$XCA") _PVFV __xc_a[];
    extern _CRTALLOC(".CRT$XCZ") _PVFV __xc_z[];    /* C++ initializers */
    extern _CRTALLOC(".CRT$XPA") _PVFV __xp_a[];
    extern _CRTALLOC(".CRT$XPZ") _PVFV __xp_z[];    /* C pre-terminators */
    extern _CRTALLOC(".CRT$XTA") _PVFV __xt_a[];
    extern _CRTALLOC(".CRT$XTZ") _PVFV __xt_z[];    /* C terminators */
    

    On initialization, the program simply iterates from ‘__xN_a’ to ‘__xN_z’ (where N is {i,c,p,t}) and calls any non null pointers it finds. If we just insert our own segment in between the segments ‘.CRT$XnA’ and ‘.CRT$XnZ’ (where, once again n is {I,C,P,T}), it will be called along with everything else that normally gets called.

    The linker simply joins up the segments in alphabetical order. This makes it extremely simple to select when our functions should be called. If you have a look in defsects.inc (found under $(VS_DIR)\VC\crt\src\) you can see that MS have placed all the “user” initialization functions (that is, the ones that initialize globals in your code) in segments ending with ‘U’. This means that we just need to place our initializers in a segment earlier than ‘U’ and they will be called before any other initializers.

    You must be really careful not to use any functionality that isn’t initialized until after your selected placement of the function pointers (frankly, I’d recommend you just use .CRT$XCT that way its only your code that hasn’t been initialized. I’m not sure what will happen if you’ve linked with standard ‘C’ code, you may have to place it in the .CRT$XIT block in that case).

    One thing I did discover was that the “pre-terminators” and “terminators” aren’t actually stored in the executable if you link against the DLL versions of the runtime library. Due to this, you can’t really use them as a general solution. Instead, the way I made it run my specific function as the last “user” function was to simply call atexit() within the ‘C initializers’, this way, no other function could have been added to the stack (which will be called in the reverse order to which functions are added and is how global/static deconstructors are all called).

    Just one final (obvious) note, this is written with Microsoft’s runtime library in mind. It may work similar on other platforms/compilers (hopefully you’ll be able to get away with just changing the segment names to whatever they use, IF they use the same scheme) but don’t count on it.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Ask A Question

Stats

  • Questions 436k
  • Answers 436k
  • Best Answers 0
  • User 1
  • Popular
  • Answers
  • Editorial Team

    How to approach applying for a job at a company ...

    • 7 Answers
  • Editorial Team

    How to handle personal stress caused by utterly incompetent and ...

    • 5 Answers
  • Editorial Team

    What is a programmer’s life like?

    • 5 Answers
  • Editorial Team
    Editorial Team added an answer It looks like the number of diggs is included in… May 15, 2026 at 3:59 pm
  • Editorial Team
    Editorial Team added an answer <% /* Is a codeblock */ for(int i = 0;i<5;i++)… May 15, 2026 at 3:59 pm
  • Editorial Team
    Editorial Team added an answer No! You cannot try to replace ntdll. It is mapped… May 15, 2026 at 3:59 pm

Trending Tags

analytics british company computer developers django employee employer english facebook french google interview javascript language life php programmer programs salary

Top Members

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.