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

  • Home
  • SEARCH
  • 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 512075
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 13, 20262026-05-13T07:16:57+00:00 2026-05-13T07:16:57+00:00

I ported my application from VC++7 to VC++9 recently. Now it sometimes crashes at

  • 0

I ported my application from VC++7 to VC++9 recently. Now it sometimes crashes at exit – the runtime starts calling global objects destructors and an access violation occurs in one of them.

Whenever I observer the call stack the top functions are:

CMyClass::~CMyClass() <- crashes here
dynamic atexit destructor for 'ObjectName'
_CRT_INIT()
some more runtime-related functions follow

The question is what is the meaning of the word “dynamic” in “dynamic atexit destructor”? Can it provide any additional information to me?

  • 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-13T07:16:57+00:00Added an answer on May 13, 2026 at 7:16 am

    its difficult to pinpoint the exact problem without the actual code, but maybe you can find it yourself after reading this:

    from http://www.gershnik.com/tips/cpp.asp

    atexit() and dynamic/shared libraries

    C and C++ standard libraries include a sometimes useful function: atexit(). It allows the caller to register a callback that is going to be called when the application exits (normally). In C++ it is also integrated with the mechanism that calls destructors of global objects so things that were created before a given call to atexit() will be destroyed before the callback and vice versa. All this should be well known and it works perfectly fine until DLLs or shared libraries enter the picture.

    The problem is, of course, that dynamic libraries have their own lifetime that, in general, could end before the main application’s one. If a code in a DLL registers one of its own functions as an atexit() callback this callback should better be called before the DLL is unloaded. Otherwise, a crash or something worse will happen during the main application exit. (To make things nasty crashes during exit are notoriously hard to debug since many debuggers have problem dealing with dying processes).

    This problem is much better known in the context of the destructors of C++ global objects (which, as mentioned above, are atexit()’s brothers). Obviously any C++ implementation on a platform that supports dynamic libraries had to deal with this issue and the unanimous solution was to call the global destructors either when the shared library is unloaded or on application exit, whichever comes first.

    So far so good, except that some implementations "forgot" to extend the same mechanism to the plain old atexit(). Since C++ standard doesn’t say anything about dynamic libraries such implementations are technically "correct", but this doesn’t help the poor programmer who for one reason or another needs to call atexit() passing a callback that resides in a DLL.

    On the platforms I know about the situation is as follows. MSVC on Windows, GCC on Linux and Solaris and SunPro on Solaris all have a "right" atexit() that works the same way as global destructors. However, GCC on FreeBSD at the time of this writing has a "broken" one which always registers callbacks to be executed on the application rather than shared library exit. However, as promised, the global destructors work fine even on FreeBSD.

    What should you do in portable code? One solution is, of course, to avoid atexit() completely. If you need its functionality it is easy to replace it with C++ destructors in the following way

    //Code with atexit()
    
    void callback()
    {
        //do something
    }
    
    ...
    atexit(callback);
    ...
    
    //Equivalent code without atexit()
    
    class callback
    {
    public: 
        ~callback()
        {
            //do something
        }
        
        static void register();
    private:
        callback()
        {}
        
        //not implemented
        callback(const callback &);
        void operator=(const callback &); 
    };
    
    void callback::register()
    {
        static callback the_instance;
    }
    
    ...
    callback::register();
    ...
    

    This works at the expense of much typing and non-intuitive interface. It is important to note that there is no loss of functionality compared to atexit() version. The callback destructor cannot throw exceptions but so do functions invoked by atexit. The callback::register() function may be not thread safe on a given platform but so is atexit() (C++ standard is currently silent on threads so whether to implement atexit() in a thread-safe manner is up to implementation)

    What if you want to avoid all the typing above? There usually is a way and it relies on a simple trick. Instead of calling broken atexit() we need to do whatever the C++ compiler does to register global destructors. With GCC and other compilers that implements so-called Itanium ABI (widely used for non Itanium platforms) the magic incantation is called __cxa_atexit. Here is how to use it. First put the code below in some utility header

    #if defined(_WIN32) || defined(LINUX) || defined(SOLARIS)
    
        #include <stdlib.h>
    
        #define SAFE_ATEXIT_ARG 
        
        inline void safe_atexit(void (*p)(SAFE_ATEXIT_ARG)) 
        {
            atexit(p);
        }
    
    #elif defined(FREEBSD)
    
        extern "C" int __cxa_atexit(void (*func) (void *), void * arg, void * dso_handle);
        extern "C" void * __dso_handle;     
    
    
        #define SAFE_ATEXIT_ARG void *
        
        inline void safe_atexit(void (*p)(SAFE_ATEXIT_ARG))
        {
            __cxa_atexit(p, 0, __dso_handle);
        }
    
    #endif
    And then use it as follows
    
    
    void callback(SAFE_ATEXIT_ARG)
    {
        //do something
    }
    
    ...
    safe_atexit(callback);
    ...
    

    The way __cxa_atexit works is as follows. It registers the callback in a single global list the same way non-DLL aware atexit() does. However it also associates the other two parameters with it. The second parameter is just a nice to have thing. It allows the callback to be passed some context (like some object’s this) and so a single callback can be reused for multiple cleanups. The third parameter is the one we really need. It is simply a "cookie" that identifies the shared library that should be associated with the callback. When any shared library is unloaded its cleanup code traverses the atexit callback list and calls (and removes) any callbacks that have a cookie that matches the one associated with the library being unloaded. What should be the value of the cookie? It is not the DLL start address and not its dlopen() handle as one might assume. Instead the handle is stored in a special global variable __dso_handle maintained by C++ runtime.

    The safe_atexit function must be inline. This way it picks whatever __dso_handle is used by the calling module which is exactly what we need.

    Should you use this approach instead of the verbose and more portable one above? Probably not, though who knows what requirements you might have. Still, even if you don’t ever use it, it helps to be aware of how things work so this is why it is included here.

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

Sidebar

Related Questions

No related questions found

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.