I have been running into strange linking behavior with g++, however, I'm just a student, and I was wondering if this was normal.
I am trying to link assembly code (machine: fedora 14 gnome 32bits x86 i686 intel i7) with c++ code and to have the assembly code call a method from a fonction instanciated in the c++ file. It seems that implementing a method in the class declaration will prevent it from being put in the linker table unless it's used at least once in the original source.
class A
{
public:
void showSUP() {
cout<<"sup";
}
};
After instanciating A, you will not be able to call _ZN1A7showSUPEv because it has not been put in the linking table:
call _ZN1A7showSUPEv
However, if you call A::showSUP() in the same .cpp as A was declared, then calling it from a seperate assembly file will work.
With (and instantiation of A)
class A
{
void showSUP();
};
A::showSUP()
{
cout<<"sup";
}
Calling _ZN1A7showSUPEv will work.
My question is, why doesn't the first example work.
Thank you all in advance.
There are attributes, that you can specifify for a function in this way
classe A
{
public:
void showSUP(){
cout<<"sup";
} __attribute__((used))
};
see gcc attribute overview
used
Found in versions: 3.1-3.4
Description:
This attribute, attached to a function, means that code must be
emitted for the function even if it appears that the function is
not referenced. This is useful, for example, when the function
is
referenced only in inline assembly.
For inlined functions the compiler
will only output code where the function is used.
Functions defined
inside the class definition are
inline (usually).
The function isn't
used.
Therefore: no function in the
binary.
In general, if you want a function to be included in the final library / executable, it need be:
used
non-inlined
And inlined function is a function whose code is simply copied and pasted where the function is used (by the compiler) so that there is no function call. It's an opportunity optimization, so a function may be inlined in some places and not inlined in others, depending on the context. Most very short functions (so-called one-liners) are generally inlined.
In the old times, to be inlined a function needed be defined in the current translation unit, that is:
either it is defined in the header (like is your case), and thus can be inlined in all sources including this header
either it is defined in a source file, and thus can be inlined in this source file
Nowadays though we also have LTO (Link Time Optimization), and if activated the linker may actually inline function calls. Those optimizations are also responsible for cleaning up the resulting library/binary from unused symbols.
There are two possible solutions to your issue:
define the function in a source file instead, it is standard and may not be wiped out
use compiler specific attributes to mark the function as used, so that it's not wiped out
In the latter case, if you wish for portability, I can only advise using a macro (ATTRIBUTE_USED) and define its content depending on the current compiler used.
Related
I am asking to see whether my understandings are correct.
inline is a suggestion to C++ compiler for substituting a function whenever it sees better, therefore calling a procedure flagged as inlined from outside of a library shouldn't be reliable and they logically should be hidden by default, preventing others to call them as an update to a compiler or codebase can be change the decision (thus removal of the inlined function and ABI breakage?).
However it seems that is not the default setting and -fvisibility-inlines-hidden should be set to make that happen. I am asking here why that is the case? Does not setting that has any real use case and it is there just because legacy reasons?
they logically should be hidden by default
C++ requires all functions (including inline functions) to have the same address in all translation units. Local statics should also be shared among all translation units. Making inline functions hidden violates those requirements if program is built as multiple shared objects (.so files).
Inline functions should have public visibility so that dynamic linker could choose one definition from all existing ones at runtime.
GCC wiki mentions this:
-fvisibility-inlines-hidden can be used with no source alterations, unless you need to override it for inlines where address identity is important either for the function itself or any function local static data.
Consider following example. Executable source:
// main.cpp
#include <cstdio>
struct A { };
inline A &foo()
{
static A a;
return a;
}
int main()
{
void *p = &foo();
std::printf("main() - %p\n", p);
}
Shared object source:
#include <cstdio>
struct A { };
inline A &foo()
{
static A a;
return a;
}
static __attribute__((constructor)) void init()
{
void *p = &foo();
std::printf("main() - %p\n", p);
}
If you build both and link executable against this shared object, you can see that foo always returns the same address in both translation units.
Now if you add __attribute__((visibility("hidden"))) to those inline functions, then you will see that address is different in different translation units.
This is not what some C++ program might expect.
Most people today think that inline has nothing to do with actual function inlining. This is not exactly true. ELF targets try to make dynamic linking transparent e.g. program should behave identically if it is build as a single executable or as multiple shared objects.
To make it possible ELF requires all functions with public visibility to be called though GOT or through PLT as if it is "imported" function. This is required so that every function could be overriden by another library (or executable itself). This also forbids inlining for all public non-inline functions (see section 3.5.5 here which shows that public function call in PIC should be made through PLT).
Code inlining for public inline functions is possible exactly because inline allows program behavior to be undefined when multiple definitions of inline function are not equivalent.
Interesting note: Clang violates this ELF requirement and is able to inline public functions on ELF targets anyway. GCC can do the same with -fno-semantic-interposition flag.
inline is a suggestion to C++ compiler for substituting a function whenever it sees better
No. This was originally the case, in perhaps the late 90s, but has not been true for a long time.
See this answer for a good explanation.
therefore calling a procedure flagged as inlined from outside of a library shouldn't be reliable
your initial assumption is already wrong, so the therefore is proceeding from a false premise
even if the compiler does inline a call (which it may do with or without the inline keyword), this is done at a specific call site. Inlining isn't something that happens to a function, which must always be emitted as usual, but to a function call.
It's entirely possible for the compiler to inline some calls to a function and not others, depending on its opinion of what will produce the best code at the call site.
Now, it's not clear what problem you believe inline causes in libraries, so it's hard to address that directly.
inline is a suggestion to C++ compiler for substituting a function whenever it sees better, therefore calling a procedure flagged as inlined from outside of a library shouldn't be reliable and they logically should be hidden by default
The compiler can still decide to inline some calls and leave some of them non-inlined. In this case you would get several copy of the inlined function in all the libraries you are linking together.
Moreover the standard somewhat requires that &foo to be the same address everywhere in your program, although the standard does not say anything about DSO/DLLs, so the compilers have some freedom in those regards (in fact, MSVC follows the opposite approach of leaving everything hidden by default).
However it seems that is not the default setting and -fvisibility-inlines-hidden should be set to make that happen.
Despite the name, -fvisibility-inlines-hidden only affects inlined class member functions. For everything else, -fvisibility=hidden should be sufficient.
Does not setting that has any real use case and it is there just because legacy reasons?
Yes. IIRC that flag was implemented in GCC 3.2 (or close enough); making it default would break a lot of legacy code.
By writing the definition of a member function inside the class in the header file as follows, I was told that compiler treats this as an inline function - hence , anywhere it encounters this function being called in the program , it enters the complete body of the function every time instead of jumping to the one location where the function resides in memory. Is this true?
class myClass
{
public:
void Fun1()
{
//implemented here
}
}
I was told that compiler treats this as an inline function
Correct. That means that it's allowed to be defined in more than one translation unit, which is necessary if you want to define it in a header and include that header more than once in your program.
Hence , anywhere it encounters this function being called in the program , it enters the complete body of the function every time instead of jumping to the one location where the function resides in memory
No, that's not what inline means in the context of a function definition. That's the optimisation of function call inlining, which the compiler can apply to any call if it thinks it will improve the code.
The two concepts are loosely related: compilers which process a single translation unit at a time will only be able to apply the optimisation to functions defined in the current unit, so they'll need to have multiple definitions to be able to optimise them in more than one unit.
If your question is whether this is equivalent to:
class myClass
{
public:
void Fun1();
};
inline void myClass::Fun1()
{
//implemented here
}
the answer is: YES.
If your question is whether the function will be physically expanded inline, the answer is: UNDEFINED. Depends on compiler's optimization flags and rules how it works.
The meaning of "inlining" in C++ is: if the compiler emits this function as out-of-line (either by not expanding at all or as alternative), it undergoes weak (vague) linkage (two such functions in two different object files linked together results in taking the first one as a good deal).
That's in contrast to normal external function, which undergo strong linkage (two such functions in two different object files linked together results in linker error).
If you define a function within a class definition, it is by default inline ( without needing to specify 'inline')
The compiler replaces all instances of an inline function call with the actual code.
Note: the compiler may ignore the 'inline' qualifier of a function if it is more than one line. You will also need to recompile all componnents (the ones which utilize that function) so that compiler can replace the code block with the new code.
You are right that the function with definition in the header file is implicitly "inline". But the inline keyword is just a hint to the compiler. Depending on its implementation, on the function contents and on the optimization flags, the compiler may decide to inline a function or not.
As far as I know it's impossible to have a function declared as "inline" in a lib file and have that function "magically inlined" into a caller function into another project (since linking is not the same as compiling and the latter happens before).
How could I inline a function when having multiple functions (into multiple libraries) that have the same declaration but different definition?
e.g.
obj1.lib
void function1() { printf("Hi"); }
obj2.lib
void function1() {printf("whatsup?"); }
main.cpp
void function1();
int main()
{
function1(); // I'd like to be able to inline this, I can steer the linking against obj1 or obj2, but I can't inline this one
}
To inline a function from an object (or a library) file you'll need this object file be compiled with link-time optimization (LTO). See Inlining functions from object files for more details.
Even if you inline functions, they always have to have the same definition: having different defintions for the same entity in a C++ program is a violation of the one definition rule (ODR) specified in 3.2 [basic.def.odr]. ODR violations are often not detected by compilers and linkers and tend to result in rather weird problems.
You'll need to make sure the functions are different, e.g., using one of these techniques:
Give them a different name.
Put the functions into a namespace.
Give the functions a different signature.
Make the static to have them visible only in the given translation units.
The simplest you can do is to give the functions different names.
If you want built-time selection of a function with a given name, that has 2 or more different implementations, and you want to support machine code inlining of that function, then declare it as inline, which requires also supplying the implementation in each variant's header, and use include and lib paths to select the relevant header (for compilation) and lib (for linking) – they'd better match. As with any inline function this doesn't guarantee machine code inlining. With respect to machine code inlining inline is just a hint (it's guaranteed effect is about permitting a definition in each translation unit, and requiring such a definition in each translation unit where it's used).
How to use include and lib paths depends on your toolchain.
Edited in response to Sam Cristall's comment.
If you mean "inline at compile time" then:
In order to use a library you need to include the header file(s) associated with that library. If the desired function is declared inline in that header and the function definition (the body of the function) is available, then the compiler will (at it's discretion) inline the function. Otherwise it won't.
If you mean "inline at link time" (an unfortunate overloading of the word "inline") than see the other answers
This question arose while I was implementing my static library.
I want to check my guess and gain information on using inline functions in static libs.
My guess is that an iplementator of a static lib can not export an inline function in his library
Due to the inline statement is
implemented by a compiler(it is up to the compiler whether to make
the function inline) by placing low level commands representing
operations in the function body to the code segment so that
operations won't be placed in the tables of export/import and
therefore can't be processed by linker and therefore can't be
included by librarian to the code of application to which static lib
is attached. Is my logic right?
I guess that importing function as inline is allowed but I wonder how it is implemented, because it is compiler`s
responsibility but on the linkage state there is only librarian, so
that means that it must undertake some actions in order to make
function inline.
Yes, inline functions are typically placed in a header, so the function body is directly visible to the compiler everywhere the function is used. This lets the compiler evaluate whether to generate inline code for the function in any particular instance.
This basically doesn't arise -- "An inline function shall be defined in every translation unit in which it is odr-used." (§3.2/3). That means if the compiler is going to generate the function inline, what goes into the library is object code that includes inline expansion of the code for that function. Since it's possible that function may not be expanded inline at every use, there will also typically be a definition of the function in the library, but that definition will be used (at least primarily) like a normal function, not expanded inline.
Linkers can also generate code though. Regardless of whether a function is or isn't an inline function by the language standard, and is defined in the same or a different translation unit from the one where it's used, the linker may be able to generate inline code for it anyway.
To make a long story short, the inline keyword has little or no effect on a typical compiler as far as whether a function's code will be generated inline or not. The main (if not sole) effect is that it changes the one-definition rule -- being inline means that multiple (identical) definitions of the same function can exist without causing a problem.
Do you understand the keyword inline - you could equally use replace.
An inline function enables the compile if so choosing to replace the function call with the actual code - nothing to export/import. It is defined in the header file. Anything that uses the object code will require that header code and thus the compiler will replace the function call with the actual code.
On Visual C++ you can use Microsoft specific behavior, and export/import inline functions with __declspec(dllexport) inline or extern inline. Note that this is Microsoft specific behavior, if you target anything but Windows and are not concerned at all with portability, you could consider it.
Consider this:
class Foo{
void func1(){
/*func1 code*/
}
void func2(){
/*func2 code*/
}
};
Case 1: class Foo in Foo.h
Case 2: class Foo nicely seperated among Foo.h and Foo.cpp
Various other cpp files include Foo.h
My question is...Will Case 1 lead to a bigger binary?
Maybe it will, maybe it won't. It really has nothing to do with header files. What matters here is that your member functions are defined in the class definition. When member functions are defined like that, they are treated as inline functions. If the compiler decides not to actually inline any calls to these functions, there won't be any impact on code size. If the compiler decides to inline any (or all) of the calls, the answer would be "it depends". Inlining calls to small functions might result in increased code size as well as in decreased code size. This all depends on the function itself and on the compiler's capabilities (optimization capabilities specifically).
If compiler decides not to inline those functions, and generate separate body for them, these bodies will appear in each object file who uses them, but with special flag for linker - 'weak symbol'. When linker finds this flag, it will combine all symbols with that name into only one resulting symbol (maybe it will produce error message if bodies or sizes of such symbols are different)
Also RTTI info and vtables also use same scenario.
With dynamic libraries, weak symbol joining may happen at run-time, if they uses the same class.
If the functions in the header are declared as static, than yes, each module (source file) that includes that header file will store a copy of that function in the object file and the final executable will be bigger in size...
If you have the code definition in the header, the compiler might create redundant copies of each function whenever you include the .h. Those redundant copies might also trigger errors from the linker, so the practice is generally frowned upon except for inline functions.
If the code for functions is included inline in the headers, then the compiler can use that to define the functions in the object code for each separate source file, or embed the function code directly where the functions are called. Depending on your compiler and linker and the support for C++ generally, that may leave you with larger code than you would have with the functions all defined separately. If the inline functions are small enough, you may save space by avoiding function call overhead. However, such functions have to be very small.