I compiled this C++ code with g++
(7.3.0).
struct C {
__attribute__((noinline)) int foo() { return 0; };
};
int bar(C &c) { return c.foo(); }
And using nm
I found that foo
is weak. Is that due to the C++ specification or a decision of GCC?
The experiment flow:
$ g++ test.cpp -c -Og
$ nm test.o
0000000000000000 T _Z3barR1C
0000000000000000 W _ZN1C3fooEv
You can define a weak symbol using either the . weak assembly directive or the weak operator in the linker command file. Assemble the source file that defines weak symbols, and include the resulting object file in the link. The "ext_addr_sym" in this example is available as a weak symbol in a final link.
__attribute__((weak)) variable attributeGenerates a weak symbol for a variable, rather than the default symbol. extern int foo __attribute__((weak)); At link time, strong symbols override weak symbols.
For c program, if you define an global variable and not initialize it, GCC will regard it as weak symbol. However, for c++ program, the default type is strong variable. That is to say, for line int gvar; in main. cpp , it is a strong symbol. Since we have another strong symbol with the same name in aux.
The __weak keyword means that the function can be overridden by creating another function with the same declaration. Many of the interrupt-functions etc. in the STM HAL libraries are declared as weak so that you can override them with your own function, instead of modifying the library functions. From GCC Manual: weak.
Is that C++ specification or decision of GCC?
A bit of both. Not that the C++ specification deals with strong or weak symbols (it doesn't). But it does affect GCC's behavior, since usually extensions try to build upon standard mandated behavior.
When you define a member function in the class body, it's automatically an inline function. In the C++ language, an inline function is a function that can have multiple definitions, so long as they appear in different translation units. It's not a problem, because in C++, an inline function must have the exact same definition in every translation unit (down to the token sequence). So even though they are "different" definitions, they are identical, and so can be reduced to a single one at some point.
The function doesn't have to actually be inlined at the call site. As far as C++ is concerend, inline
is about the one-definition rule and linkage. So you have that, there can be multiple definitions of C::foo
according to the spec.
And then you specify __attribute__((noinline))
, so the function cannot be physically inlined, and so every TU must contain a symbol for the function.
This leaves only one choice. The symbol must be weak, otherwise the different symbols in different translation units will interfere with eachother. By making the symbol weak, you can have your mandatory definition and avoid physically inlining the function, while the C++ specification is upheld. Those different symbols stand for the exact same function, and so any one of them can "win" when linking.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With