1

I am in a discussion in one of the code review sessions.

The debate is about if the functions in the anonymous namespace should be declared static or not. As an example, I am being told the square3 function which declared with "static" keyword has advantages.

namespace {
int square2(int num) {
    return num * num;
}

static int square3(int num) { 
    return num * num;
}

}

I have told by my colleagues static is beneficial because:

A static function does not require an entry in the function table and thus does not require time or memory when linking.

static means it is not exposed when linking. It improves linking time and reduces memory usage when linking. Anonymous namespace does not provide this.

I think by "function table" my colleagues mean "symbol table". I couldn't find any documentation about that except the least upvoted answer of another S.O question which says

It is usually better to prefer static linkage, as that doesn't pollute the symbol table

I am trying to see if that info is true or not by using compiler explorer. But I couldn't find a way to get to the symbol table. All I see the function names and everything is mangled in the same way.

So I have two questions:

1 - Is using a function with static keyword in the anonymous namespace helps with memory/linking time?

2 - Is there a way to check the symbol table in compiler explorer?

Kadir Erdem Demir
  • 3,531
  • 3
  • 28
  • 39
  • 1
    For 2. you can add the `readelf` tool and check the symbol table with `--symbols`. like this https://godbolt.org/z/dsW1xd – The Philomath Jan 29 '21 at 10:10
  • Thanks a lot. I can see an extra symbol under "Symbol table '.symtab' contains 65 entries:" I am not sure what .symtab though. – Kadir Erdem Demir Jan 29 '21 at 13:00
  • 1
    `E`xecutable and `L`inkable `F`ormat defines how the executable binary is structured. It has sections and out of those sections two sections are for symbols in the executable generated at compiler explorer. `.symtab` is the name of one of those 2 sections. – The Philomath Jan 29 '21 at 13:11
  • That was very helpful is it possible to post an answer. It can be useful for some other readers as well. – Kadir Erdem Demir Jan 29 '21 at 13:31

2 Answers2

3

It improves linking time and reduces memory usage when linking.

Even if this were to be true for a given implementation, from a pure language perspective, a static function in an unnamed namespace is redundant and arguably an anti-pattern that is likely to confuse other developers; whom may already struggle with the way C++ has overloaded what static means in terms of linkage and the entirely orthogonal storage duration.

// .cpp
namespace top {

       int a{};  // external linkage, static storage duration
const  int b{};  // internal linkage, static storage duration
static int c{};  // internal linkage, static storage duration

namespace {

       int d{};  // internal linkage, static storage duration
const  int e{};  // internal linkage, static storage duration
static int f{};  // internal linkage, static storage duration
// ^^^ static is redundant (-> and may confuse devs)

       int g() {}  // internal linkage
static int h() {}  // internal linkage
// ^^^ static is redundant (-> and may confuse devs)

}  // namespace

       int k() {}  // external linkage
static int l() {}  // internal linkage

}  // namespace top

[...] except the least upvoted answer of another S.O question which says

It is usually better to prefer static linkage, as that doesn't pollute the symbol table

The answer you refer to was based on C++03, where entities in unnamed namespace did not have internal linkage per default. Meaning that in C++03, even if an entity in an unnamed namespace was not accessible to other translation units (due to the unique naming nature of the unnamed namespace), it could still have external linkage and thus end up in the symbol table.

From C++11 and onwards entities in an unnamed namespace have internal linkage. Meaning that, from the C++ language perspective w.r.t. linkage, the examples above (with internal linkage) are equivalent, and it could arguably even be the case that your colleague mixes these concepts (as is common due to their overloaded meaning) or that you colleagues' argument is based on the state of affairs prior to C++11.

dfrib
  • 70,367
  • 12
  • 127
  • 192
1

1 - Is using a function with static keyword in the anonymous namespace helps with memory/linking time?

Static does not affect functions in anonymous namespace as far as the language is concerned. This is because being in an anonymous namespace already achieves the same thing as declaring the function static achieves. (Note that declaring a member function static has an entirely different meaning).

2 - Is there a way to check the symbol table in compiler explorer?

I don't know of compiler explorer, but you can use for example the nm program to list symbols: http://coliru.stacked-crooked.com/a/0281bc487044ec02

namespace {

       void foo1(){} // internal linkage
static void foo2(){} // internal linkage

}

       void foo3(){} // external linkage
static void foo4(){} // internal linkage

command:

nm main.o | c++filt

output:

0000000000000000 T foo3()
eerorika
  • 232,697
  • 12
  • 197
  • 326
  • Thanks a lot, I have one question though. It seems there is only one symbol for the externally linked function. Can I take it as, for internal linkage, there won't be any symbols never. – Kadir Erdem Demir Jan 29 '21 at 10:57
  • @KadirErdemDemir There can certainly be symbols for functions with internal linkage. Leaving them out can be considered to be an optimisation. If there are calls to interanl functions that have not been expanded inline, then those functions cannot be optimised away. It would be a local symbol rather than global one. – eerorika Jan 29 '21 at 11:08
  • I have another question. As suggested by @The Philomath in the comment section of my question; I used Godbolt (https://godbolt.org/z/1nvKhe) and managed to find an extra symbol coming from the static function " 39: 0000000000401102 15 FUNC LOCAL DEFAULT 12 _ZN12_GLOBAL__N_". It shows up whether I use static or not. The only question in my mind why it does not shows up in your link. And if mine is reliable or not ? – Kadir Erdem Demir Jan 29 '21 at 12:59
  • @KadirErdemDemir You didn't enable the optimiser, so it didn't inline the function call , so it couldn't leave out the local symbol. – eerorika Jan 29 '21 at 13:01
  • So I think that the conclusion, internally linked variables/functions always creates an entry in the symbol table unless function is inlined as shown in the godbolt example. Do you agree @eerorika? – Kadir Erdem Demir Jan 29 '21 at 14:24
  • @KadirErdemDemir In the local symbol table, yes. – eerorika Jan 29 '21 at 14:28