Function call immediately before the main

Is it possible to register a function that will be launched immediately before entering main ? I know that all global objects are created before main entered, so I can put the code in the constructor of the global object, but this does not guarantee any specific order. What I would like to do is add the registration code to the constructor, but, alas, I do not know what to put there :) I assume that this is very specific to the system?

+7
source share
4 answers

If you use gcc , you can use the constructor attribute for the function that it called before main (see the documentation for more details).

constructor

destructor

The constructor attribute causes the function to call automatically before main () starts. Similarly, the destructor attribute causes the function to be called automatically after the completion of main () or exit () . Functions with these attributes are useful for initializing data that will be used implicitly during program execution.

+9
source

Not sure if this is exactly what you want ... But he has to do the job.

 int main() { static int foo = registerSomething(); } 

It is better to explicitly call such registration functions, either mainly or on first access (but the first access init can cause problems if you are multi-threaded).

+2
source

I guess here, but:

  • Do you want to register something in another compiler
  • You are having a registration problem because the global variables in which you save the registration are not yet built.

C ++ determines that the-static function is initialized sometime before it is first available, so you can bypass it as shown below.

 typedef std::map<std::string, std::string> RegistrationCache; RegistrationCache& get_string_map() { static RegistrationCache cache; return cache; } class Registration { Registration(std::string name, std::string value) { get_string_map()[name] = value; } }; 
+1
source

purpose

Say you want the following:

 STATIC_EXECUTE { printf("This probably prints first"\n"); } STATIC_EXECUTE { printf("But order isn't guaranteed in the language spec, IIRC"\n"); } int main(int argc, char **argv) { printf("This definitely prints last. Buh Bye.\n"); } 

Implementation

C ++ version - static variable + constructor:

 // This is some crazy magic that produces __StaticExecute__247 // Vanilla interpolation of __StaticExecute__##__LINE__ would produce __StaticExecute____LINE__ // I still can't figure out why it works, but it has to do with macro resolution ordering // If you already have Boost, you can omit this part #define BOOST_PP_CAT(a, b) BOOST_PP_CAT_I(a, b) #define BOOST_PP_CAT_I(a, b) BOOST_PP_CAT_II(~, a ## b) #define BOOST_PP_CAT_II(p, res) res // This avoids repeating the BOOST_PP_CAT 5X #define STATIC_EXECUTE \ STATIC_EXECUTE_I(BOOST_PP_CAT(__StaticExecute__, __LINE__)) // This is the meat, a static instance of a class whose constructor runs your code #define STATIC_EXECUTE_I(uniq_name) \ static struct uniq_name { \ uniq_name(); \ } BOOST_PP_CAT(uniq_name, __var); \ uniq_name::uniq_name() // followed by { ... } 

Version C - Static Variable + Function

 // ... // The meat: a static variable initialized from a function call #define STATIC_EXECUTE_I(uniq_name) \ static void uniq_name (); \ static int BOOST_PP_CAT(uniq_name, __var) = \ (uniq_name(), 0); \ static void uniq_name() // followed by { ... } 

Notes

  • IMHO, the C ++ version is a bit more elegant. In theory, it consumes a little less space. Otherwise, potatoes, tat-o.

  • Caution: I have not tested the version of "C" on my own C-only compiler. Crossed fingers; post a note if it doesn't work.

  • Caution: compiler compatibility in general is a complex thing. I would not be shocked if there is an error in the compiler.

  • The code BOOST_PP_CAT is stolen from boost / preprocessor / cat.hpp . I simplified the implementation, and portability might have been violated in this process. If this does not work, try the original (more detailed) implementation and post a comment below. Or, if you are already using Boost, you can simply use their version.

  • If you are trying to understand the magic of Boost, note that (at least for me in this scenario too) the following also works:

  #define BOOST_PP_CAT(a, b) BOOST_PP_CAT_I(a, b) #define BOOST_PP_CAT_I(a, b) a ## b 
0
source

All Articles