2

Consider the case of a class member function defined in a header, with a static storage variable. When you include the header in multiple compilation units, you will end up with multiple copies of the static variable. However, the compiler will fix this for you, and just pick one of the emitted variables (note that this is different from inlining). This is enabled by a GNU specific extension to the possible types of a symbol, precisely gnu_unique_object (they show up as "u" in nm, which calls them in the man pages "unique global symbols").

The question is, how do you force the compiler to produce this kind of symbols for arbitrary variables? I'm tired of wrapping things in a class to get this behavior.

Lorenzo Pistone
  • 5,028
  • 3
  • 34
  • 65
  • The link you provide describes a behavior that has been specifically implemented for loadable modules (aka shared libraries). Is it the context in which you intend to use your static variables ? You speak about multiple compilation units, but not multiple shared libraries. If not, then you can certainly make things simpler. Please simply tell us what is the behavior you expect for these variables in the end. – dim Apr 27 '16 at 09:15
  • @dim it may have been implemented for shared libraries, but gcc uses it to implement the behavior that I described. – Lorenzo Pistone Apr 27 '16 at 10:51
  • Fine, but I still don't understand: when you say "a class member function defined in a header, with a static storage variable". Do you mean "a variable defined with static storage, declared within the body of a member function of some class" ? Or a class containing both "a member function" and "a member variable with static storage" ? – dim Apr 27 '16 at 11:16
  • A variable defined with static storage, declared within the body of a member function of some class in a header, so that it can happen that it is included in multiple compile units. – Lorenzo Pistone Apr 27 '16 at 11:27
  • Ok, then, you just don't need to wrap this in a class. Any variable declared static within the body of a function (whether it is a member of a class or a good old C-style function) will have this behavior. Declare the function inline if you want to have it in a header. – dim Apr 27 '16 at 11:34
  • well there's still the wrapper function (typically `int& get_my_unique_int(){...}`). I would just like to have just the bare `int something __attribute__((unique));`. – Lorenzo Pistone Apr 27 '16 at 13:35
  • Then it simply becomes a global variable. That's why I don't understand where the problem is. – dim Apr 27 '16 at 14:28
  • I assume the problem is that he's declaring the global variable in a header, and that's (predicably) not working, so he's found a workaround, which is where all the confusion about members and statics comes into play. http://stackoverflow.com/questions/8108634/global-variables-in-header-file – Jfevold May 01 '16 at 16:44

2 Answers2

1

Since C++ 17, one can use inline variables. They produce gnu_unique_object symbols:

$ cat c1.cpp
inline int var1 = 123;

void f1() {
    int x = var1;
}
$ g++ -std=c++1z -c c1.cpp
$ nm -C c1.o
0000000000000000 T f1()
0000000000000000 u var1
Ivan
  • 1,552
  • 1
  • 16
  • 25
0

If you declare the global variable in a header file, then you'll get a different instantiation of that variable in each compilation unit. The extern keyword is what you're after. This keyword makes what looks like an instantiation into a forward declaration. It can be thought of as a promise that a variable of that name is instantiated in a different compilation unit, and will be findable upon linking.

MyTrueGlobals.h

extern int global_variable_1;

MyTrueGlobals.cpp

int global_variable_1 = 0;
Jfevold
  • 422
  • 2
  • 11
  • That's exactly what I'm trying to avoid, and *it is possible* to avoid, by doing what I described in the question. – Lorenzo Pistone May 02 '16 at 09:04
  • What are you avoiding? Having to have a cpp file? Nobody here seems to understand your question, myself included. @dim's comment above is probably your best bet, the behavior of the `inline` keyword seems to be what you're after, but it can only apply to functions (as I understand it). – Jfevold May 02 '16 at 13:42