简体   繁体   中英

How to force the initialization of a static local variable before main?

Consider the pair of functions below:

double MYAPI foo(double x) { 
     return x; 
}
Register register_foo_([] { 
     return reg(&foo, "foo", ...); // function name repeated used
});

register_foo_ is a global variable, initialized before dllmain , whose constructor takes a lambda that repeatedly references the name of the function above it literally. It would be great if the registration code can move inside the function above to reduce the chance of making an error. I tried:

double MYAPI foo(double x) { 
     static Register register_foo_([] { 
          return reg(&foo, "foo", ...); // static local does not initialize before dllmain
     });
     return x; 
}

If the above code works, then I can easily turn it into a macro that makes use of __FUNCNAME__ . Is there a way to force the initialization of static local variable register_foo_ before dllmain?

Static variables local to a function (method) are initialized on first use of the function they're in. (They're zero-initialized at program load, then initialized "properly" via code when the function is first entered.) See the answers to this question . So your proposed movement of that code into the function changes the semantics of initialization, and it won't work.

Your original code worked, so what you apparently wanted was to move the code inside the function so it was somehow tied closer together in your mind - or the mind of a reader of the code - so that you could see that your string constant name and function name were right. Also maybe so that you could ensure the registration was done. And therefore what you want is to accomplish DRY.

The traditional (and only) way to accomplish that is by using a preprocessor macro that expands into the registration call and the function header.

You proposed using a macro yourself - now expand the macro so it not only generates the registration function but also the function header.

This runs a function before main() , not sure if it will work for dllmain() :

#include <iostream>

int func_before_main()
{
    std::cout << "func_before_main()" << '\n';
    // do before main stuff
    return 0;
}

const int dummy = func_before_main();

int main()
{
    std::cout << "main()" << '\n';
}

Output:

func_before_main()
main()

I suppose you want to achieve a syntax similar to:

DEFINE_FUNC(void, foo, (double x)) {
    return x;
}

... and have the boilerplate autogenerated. That's actually very simple to do if you bring the Register above the function, with the help of a declaration:

#define DEFINE_FUNC(Ret, name, args)   \
    Ret name args;                     \
    Register register_##name##_([] {   \
        return reg(&name, #name, ...); \
    });                                \
    Ret name args

No, there's not. That's your answer.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM