2

I have the following in bla.h:

#include <iostream>

static inline void bla() {
  static int x;
  std::cout << "bla @ " << (uintptr_t)bla << ": x @ " << &x << std::endl;
}

Then bla() is called from 2 separate translation units resulting in this output:

bla @ 94796100194693: x @ 0x56376fe10178
bla @ 94796100194897: x @ 0x56376fe10180

This is a bit surprising to me after reading inline specifier.

It says:

In an inline function,

  • Function-local static objects in all function definitions are shared across all translation units (they all refer to the same object defined in one translation unit)

In that sentence it does NOT restrict this to "with external linkage (e.g. not declared static)" like it does in the paragraph before that for "It has the same address in every translation unit".

So I expected the output to show different addresses for bla but identical addresses for x.

Is this a bug in g++?

Note: This is specific to the changed meaning of inline in C++17.

Goswin von Brederlow
  • 11,875
  • 2
  • 24
  • 42
  • 3
    `static` on a function means each translation unit gets its own copy of that function - they are all distinct; and so static local variables inside are also distinct. – Igor Tandetnik Oct 20 '20 at 04:07
  • 1
    The actual text of the C++ standard has this note in **[dcl.inline]/6**: "A static local variable in an inline function **with external linkage** always refers to the same object." Emphasis mine. – Igor Tandetnik Oct 20 '20 at 04:12
  • @IgorTandetnik Please make that an answer then with links to the actual standard text – Goswin von Brederlow Oct 20 '20 at 05:56
  • To whoever marked this as duplicate: This is not a duplicate of a 12 year old question. The meaning of inline in c++ was changed in c++17 and 12 years back that standard didn't even exist. None of the answers there go beyond c++14. – Goswin von Brederlow Oct 20 '20 at 05:56
  • Ah, in that case, please edit the question to say that exactly, and add the c++17 tag. Making a comment is less useful as it may not be noticed, but if you edit the question, it goes into the reopen queue. – cigien Oct 20 '20 at 13:00
  • 1
    I don't think that C++17 changed anything wrt inline functions and function static variables. The new inline variables are at file scope - outside of (inlne) functions and thus never function static variables. – Paul Floyd Oct 29 '20 at 09:16

1 Answers1

0

As Igor Tandetnik commented the error is on cppreference.com as they left out an important part of the standard:

The actual text of the C++ standard has this note in [dcl.inline]/6: "A static local variable in an inline function with external linkage always refers to the same object."

Emphasis mine. – Igor Tandetnik Oct 20 at 4:12

So the observed behavior is according to the standard.

Goswin von Brederlow
  • 11,875
  • 2
  • 24
  • 42
  • This isn’t a good *way* of thinking about it: such declarations with internal linkage declare **unrelated** functions, some of which might not have “the” variable in question (or have “it” have a different type or value). Suitable declarations with external linkage declare a **single** function, so of course there is just the one static local variable. C++23 is expected to rewrite that note to avoid suggesting that somehow the function’s *address* is separate from its *identity*. – Davis Herring Oct 31 '20 at 00:51
  • @DavisHerring The point is that cppreference.com dropped the **external linkage** suggesting that declarations with internal linkage would share their static variables but not their identity. So functions with internal linkage would overwrite each others static variables which might even have different types. – Goswin von Brederlow Nov 01 '20 at 01:02
  • That’s not a plausible reading: why would variables in different functions (and possibly with different types) be the same variable (or otherwise have the same address)? The question is why Cppreference included such a statement anywhere (since it’s implied by “an inline function”, singular), and the answer is probably that the standard sometimes says silly things along those same lines—as in the note that you quote and that’s being removed. – Davis Herring Nov 01 '20 at 07:45
  • Because for inline functions with external linkage no matter how many instances of the function and variables you have they become all identical. That's the change that was codified in C++17. – Goswin von Brederlow Nov 03 '20 at 15:10
  • Assuming the ODR is being followed, there is only one function! There are no “instances” that “become all identical”. And this is unchanged since C++98. – Davis Herring Nov 03 '20 at 15:15
  • During compile every translation unit can have an instance of the function and variables. When linking they become one. And no, this has changed over time. Used to be you got a "multiple definitions" error during linking when an inline function appeared in multiple translation units. – Goswin von Brederlow Nov 03 '20 at 15:30
  • I’m talking about the language, not the details of even typical implementations. And you never got multiple-definition errors for inline functions, except perhaps in C where the meaning of `inline` is different. – Davis Herring Nov 03 '20 at 17:04