Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

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?

like image 435
Candy Chiu Avatar asked Jun 09 '16 16:06

Candy Chiu


People also ask

Are static variables initialized before main?

Global (namespace) variables or static class members 1 live for the entire execution of the program: they must be initialized before main() is run and destroyed after execution finishes.

How do you initialize a static variable?

For the static variables, we have to initialize them after defining the class. To initialize we have to use the class name then scope resolution operator (::), then the variable name. Now we can assign some value.

Is initialization necessary for local static variables?

It is mandatory to initialize the static variable using the static keyword in C else it will return an error. The static variable is only initialized the first time when a function is called. In a static variable, the memory of a static variable is allocated.

Can a static variable be initialized in a method?

The only way to initialize static final variables other than the declaration statement is Static block. A static block is a block of code with a static keyword. In general, these are used to initialize the static members. JVM executes static blocks before the main method at the time of class loading.


2 Answers

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.

like image 86
davidbak Avatar answered Sep 28 '22 03:09

davidbak


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
like image 40
Quentin Avatar answered Sep 28 '22 02:09

Quentin