How did you find out whether the main one came out?

In C and C ++, atexit functions are called either inside exit or after main returned (which conditionally calls exit : __libc_start_main(argc,argv) { __libc_constructors(); exit(main(argc,argv)); } ).

Is there a way to find out if we are inside the exit sequence? C ++ global and local statistics destructors are registered using atexit , so your code can certainly be called at this point. (Interestingly, on some platforms, if you try to create a locally static C ++ object inside exit , it blocks the exit lock!)

My best attempt is as follows:

 static bool mainExited = false; static void watchMain() { static struct MainWatcher { ~MainWatcher() { mainExited = true; } } watcher; } 

If you want to look at exit, you call watchMain() , and mainExited tells you at any time whether the exit sequence has been started, except, of course, if the destroyed locally static object is followed by initialization

Is it possible to improve the technique to fix this, or is there another way that will work?

In addition - a precedent!

While the problem is interesting from a language point of view (a bit like "can I determine if I am inside the atexit block and JNI_OnUnload not called if the shared JNI library is not unloaded by the class loader.

Since shared library objects can be destroyed both by explicitly destroying them (and must free their resources) and by clearing upon exit, I need to safely distinguish between these two cases, since the JVM will disappear by the time we reach the exit code! Basically, without a little sniffing, I just can’t find the JNI specifications / documents for the shared library to find out if there is a JVM or not, and if it is gone, then, of course, it’s wrong to try to free the links that we have to Java objects .

+6
source share
2 answers

The real problem here is that the semantics of the property you specified are mixed up. The JVM kinda owns your shared library, but it is not there either. You have a bunch of references to Java objects that you sometimes need to clean up, but sometimes you don't.

The real solution here is simply not to contain references to Java objects as global variables. Then you will not need to know if the JVM exists or not when the library is unloaded for some reason. Just keep references to Java objects from within the objects referenced by Java, and then let the JVM take care of whether they need to free them.

In other words, do not take responsibility for cleaning when exiting first.

+7
source

Your observer should not rely on any static initialization order:

 #include <iostream> struct MainWatcher // : boost::noncopyable { enum MainStatus { before, during, after }; MainWatcher(MainStatus &b): flag(b) { flag = during; } ~MainWatcher() { flag = after; } MainStatus &flag; }; ////////////////////////////////////////////////////////////////////// // Test suite ////////////////////////////////////////////////////////////////////// // note: static data area is zero-initialized before static objects constructed MainWatcher::MainStatus main_flag; char const *main_word() { switch(main_flag) { case MainWatcher::before: return "before main()"; case MainWatcher::during: return "during main()"; case MainWatcher::after: return "after main()"; default: return "(error)"; } } struct Test { Test() { std::cout << "Test created " << main_word() << "\n"; } ~Test() { std::cout << "Test destroyed " << main_word() << "\n"; } }; Test t1; int main() { MainWatcher watcher(main_flag); // rest of code Test t2; } 
+1
source

Source: https://habr.com/ru/post/983693/


All Articles