Related
I have a project in pure C - st usb library and I need to migrate it to c++ and change same structures into classes. I removed all c++ "protections" like:
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
I changed all files extensions from .c to .cpp (except HAL library).
I realized that c++ .hex is 7kB smaller then c .hex. When I looked into .map file I saw that many functions are missing. I thought that staticfunctions caused that, but removing static key word didn't help. Does anyone have idea what could cause that some functions weren't compiled. When extensions are .c everything is fine.
I can think of two main reasons:
Inlining. The compiler can decide there is no need to emit the function as a standalone function if all usages can be inlined.
Unused code. The compiler can see that a function isn't used anywhere in your code and decide to eliminate it from the final result.
If the result is to be used as sort of library, that your environment calls specific functions without having an explicit call in your own code, I think the best method is to compile and link your code as a library (probably dynamic lib) and exporting those functions as library interface (visibility in gcc, dllexport in MSVC) will force the compiler/linker to include them in the produced binary even if they don't see why they are needed right now.
(Of course, this is a wild guess about your target environment.)
Another option is to turn off the specific compiler/linker optimizations for removing dead code and forcing emitting standalone function instance for inlined functions, but I think it's very indirect approach, have a wider effect and can complicate maintenance later.
C++ functions are given different signatures than C functions. Since you lost functionality and the code is much smaller, it's likely that a function that requires C linkage is being compiled as C++ and the signature mismatch is preventing proper linking.
A likely place for this to happen is in the interrupt vector table. If the handler function is compiled with C++ linkage, the handler address won't make it into a table that's compiled with C.
Double check the interrupt vectors and make sure that they reference the correct functions. If they are correct, check any other code compiled with C that might reference an external symbol compiled with C++.
The reason we have to define inline functions in the header is that each compilation unit where that function is called must have the entire definition in order to replace the call, or substitute it. My question is why are we forced to put a definition in a header file if the compiler can and does do its own optimisations of inlining, which would require it to dig into the cpp files where the functions are defined anyway.
In other words, the compiler seems to me to have the ability to see the function "declaration" in a header file, go to the corresponding cpp file and pull the definition from it and paste it in the appropriate spot in the other cpp. Given that this is the case, why the insistence of defining the function in the header, implying as if the compiler can't "see" into other cpp files.
The MSDN says about Ob2/ optimisation setting:
Ob2/ The default value. Allows expansion of functions marked as inline, __inline, or __forceinline, and any other function that the compiler chooses (My emphasis).
The reason we're forced to provide definitions of inline function in header files (or at least, in some form that is visible to the implementation when inlining a function in a given compilation unit) is requirements of the C++ standard.
However, the standard does not go out of its way to prevent implementations (e.g. the toolchain or parts of it, such as the preprocessor, compiler proper, linker, etc) from doing things a little smarter.
Some particular implementations do things a little smarter, so can actually inline functions even in circumstances where they are not visible to the compiler. For example, in a basic "compile all the source files then link" toolchain, a smart linker may realise that a function is small and only called a few times, and elect to (in effect) inline it, even if the points where inlining occurs were not visible to the compiler (e.g. because the statements that called the functions were in separate compilation units, the function itself is in another compilation unit) so the compiler would not do inlining.
The thing is, the standard does not prevent an implementation from doing that. It simply states the minimum set of requirements for behaviour of ALL implementations.
Essentially, the requirement that the compiler have visibility of a function to be inlined is the minimum requirement from the standard. If a program is written in that way (e.g. all functions to be inlined are defined in their header file) then the standard guarantees that it will work with every (standard compliant) implementation.
But what does this mean for our smarter tool-chain? The smarter tool-chain must produce correct results from a program that is well-formed - including one that defines inlined functions in every compilation unit which uses those functions. Our toolchain is permitted to do things smarter (e.g. peeking between compilation units) but, if code is written in a way that REQUIRES such smarter behaviour (e.g. that a compiler peek between compilation units) that code may be rejected by another toolchain.
In the end, every C++ implementation (the toolchain, standard library, etc) is required to comply with requirements of the C++ standard. The reverse is not true - one implementation may do things smarter than the standard requires, but that doesn't generate a requirement that some other implementation do things in a compatible way.
Technically, inlining is not limited to being a function of the compiler. It may happen in the compiler or the linker. It may also happen at run time - for example "Just In Time" technology can, in effect, restructure executable code after it has been run a few times in order to enhance subsequent performance [this typically occurs in a virtual machine environment, which permits the benefits of such techniques while avoiding problems associated with self-modifying executables].
The inline keyword isn't just about expanding the implementation at the point it was called, but in fact primarily about declaring that multiple definitions of a function may exist in a given translation unit.
This has been covered in other questions before, which can it explain much better than I :)
Why are class member functions inlined?
Is "inline" implicit in C++ member functions defined in class definition
No, compilers traditionally can't do this. In classic model, compiler 'sees' only one cpp file at a time, and can't go to any other cpp files. Out of this cpp file compiler so-called object file in platofirm native format, which is than linked using effectively linker from 1970s, which is as dumb as a hammer.
This model is slowly evolving. With more and more effective link-time optimizations (LTO) linkers become aware of what cpp code is, and can perform their own inlining. However, even with link-time optimization model compiler-done inlining and optimization are still way more efficient than link-time - a lot of important context is lost when cpp code is converted to intermediate format suitable for linking.
It's much easier for the compiler to expand a function inline if it has seen the definition of that function. The easiest way to let the compiler see the definition of a function in every translation unit that uses that function is to put the definition in a header and #include that header wherever the function will be used. When you do that you have to mark the definition as inline so that the compiler (actually the linker) won't complain about seeing the definition of that function in more than one translation unit.
I'm writing code (using GCC 4.7.2), where I'm excessively logging stuff during the testing phase in countless positions of the code. These loggings should disappear on the release binary.
I'm doing the logging via a function just like void log(std::string msg);. As these function calls are many and distributed via the whole code in many files, I had the idea to make it an inline function and just give it an empty body for the release binary.
No my question is: what does the compiler do with it? Does the binary just contain the rest of the code without the function, does it contain a nop, or anything else? Could I eliminate the logging code from the binary completely by emptying the inline logging function?
I'm not only interested in an answer to solve the problem but I'm also curious about the compiler's behaviour itself.
If you want different code between debug and release, then that's an ideal use case for the preprocessor:
#ifdef NDEBUG
#define log(ignored)
#endif
Then you're not leaving anything up to the compiler. You're guaranteed that only the debug version will have the extra calls. This is how assert works, too.
Note that this will also drop the parameter computation. For example, if you have log(get_msg()) then the macro method will drop the call to get_msg() as well. This is probably desirable, but you need to be aware of it.
As for inline, that's entirely up to the compiler. The inline keyword itself is only a hint, it does not obligate the compiler to do anything. The compiler performs its own optimization calculations on whether or not to inline a particular function (that includes inlining functions not marked inline). That typically means a sufficiently high optimization level (i.e. -O3), and that the body of the inline function is visible in that particular compilation unit. For example, if the compiler only sees a declaration but the (maybe empty) function body is in a different .cpp file, then it cannot inline. But yes, if the compiler determines that there are no side effects, it is free to make the whole function disappear.
But again, there's no reason to depend on that when the preprocessor offers such a clean and widely used solution.
You might or might not be left with a trivially empty function (if for example, the function's address is used to make a pointer, then the function needs to exist).
But all inlined call sites will turn into nothing. (And the compiler should choose to always inline direct calls to a function it can see is empty -- Adam's answer is correct about calls into other translation units making this difficult, but Whole Program Optimization can help even there)
Do note, however, that parameters to an inline function will still be evaluated. They might also get inlined and mostly eliminated, but side effects in parameters will occur. This is rather different from using a #define macro to eliminate the entire log(...) string from the source code. The macro gets rid of the parameter computations, too.
What is the advantages/disadvantages of using inline functions in C++? I see that it only increases performance for the code that the compiler outputs, but with today's optimized compilers, fast CPUs, huge memory etc. (not like in the 1980< where memory was scarce and everything had to fit in 100KB of memory) what advantages do they really have today?
Advantages
By inlining your code where it is needed, your program will spend less time in the function call and return parts. It is supposed to make your code go faster, even as it goes larger (see below). Inlining trivial accessors could be an example of effective inlining.
By marking it as inline, you can put a function definition in a header file (i.e. it can be included in multiple compilation unit, without the linker complaining)
Disadvantages
It can make your code larger (i.e. if you use inline for non-trivial functions). As such, it could provoke paging and defeat optimizations from the compiler.
It slightly breaks your encapsulation because it exposes the internal of your object processing (but then, every "private" member would, too). This means you must not use inlining in a PImpl pattern.
It slightly breaks your encapsulation 2: C++ inlining is resolved at compile time. Which means that should you change the code of the inlined function, you would need to recompile all the code using it to be sure it will be updated (for the same reason, I avoid default values for function parameters)
When used in a header, it makes your header file larger, and thus, will dilute interesting informations (like the list of a class methods) with code the user don't care about (this is the reason that I declare inlined functions inside a class, but will define it in an header after the class body, and never inside the class body).
Inlining Magic
The compiler may or may not inline the functions you marked as inline; it may also decide to inline functions not marked as inline at compilation or linking time.
Inline works like a copy/paste controlled by the compiler, which is quite different from a pre-processor macro: The macro will be forcibly inlined, will pollute all the namespaces and code, won't be easily debuggable, and will be done even if the compiler would have ruled it as inefficient.
Every method of a class defined inside the body of the class itself is considered as "inlined" (even if the compiler can still decide to not inline it
Virtual methods are not supposed to be inlinable. Still, sometimes, when the compiler can know for sure the type of the object (i.e. the object was declared and constructed inside the same function body), even a virtual function will be inlined because the compiler knows exactly the type of the object.
Template methods/functions are not always inlined (their presence in an header will not make them automatically inline).
The next step after "inline" is template metaprograming . I.e. By "inlining" your code at compile time, sometimes, the compiler can deduce the final result of a function... So a complex algorithm can sometimes be reduced to a kind of return 42 ; statement. This is for me extreme inlining. It happens rarely in real life, it makes compilation time longer, will not bloat your code, and will make your code faster. But like the grail, don't try to apply it everywhere because most processing cannot be resolved this way... Still, this is cool anyway...:-p
Inline functions are faster because you don't need to push and pop things on/off the stack like parameters and the return address; however, it does make your binary slightly larger.
Does it make a significant difference? Not noticeably enough on modern hardware for most. But it can make a difference, which is enough for some people.
Marking something inline does not give you a guarantee that it will be inline. It's just a suggestion to the compiler. Sometimes it's not possible such as when you have a virtual function, or when there is recursion involved. And sometimes the compiler just chooses not to use it.
I could see a situation like this making a detectable difference:
inline int aplusb_pow2(int a, int b) {
return (a + b)*(a + b) ;
}
for(int a = 0; a < 900000; ++a)
for(int b = 0; b < 900000; ++b)
aplusb_pow2(a, b);
In archaic C and C++, inline is like register: a suggestion (nothing more than a suggestion) to the compiler about a possible optimization.
In modern C++, inline tells the linker that, if multiple definitions (not declarations) are found in different translation units, they are all the same, and the linker can freely keep one and discard all the other ones.
inline is mandatory if a function (no matter how complex or "linear") is defined in a header file, to allow multiple sources to include it without getting a "multiple definition" error by the linker.
Member functions defined inside a class are "inline" by default, as are template functions (in contrast to global functions).
//fileA.h
inline void afunc()
{ std::cout << "this is afunc" << std::endl; }
//file1.cpp
#include "fileA.h"
void acall()
{ afunc(); }
//main.cpp
#include "fileA.h"
void acall();
int main()
{
afunc();
acall();
}
//output
this is afunc
this is afunc
Note the inclusion of fileA.h into two .cpp files, resulting in two instances of afunc().
The linker will discard one of them.
If no inline is specified, the linker will complain.
Inlining is a suggestion to the compiler which it is free to ignore. It's ideal for small bits of code.
If your function is inlined, it's basically inserted in the code where the function call is made to it, rather than actually calling a separate function. This can assist with speed as you don't have to do the actual call.
It also assists CPUs with pipelining as they don't have to reload the pipeline with new instructions caused by a call.
The only disadvantage is possible increased binary size but, as long as the functions are small, this won't matter too much.
I tend to leave these sorts of decisions to the compilers nowadays (well, the smart ones anyway). The people who wrote them tend to have far more detailed knowledge of the underlying architectures.
Inline function is the optimization technique used by the compilers. One can simply prepend inline keyword to function prototype to make a function inline. Inline function instruct compiler to insert complete body of the function wherever that function got used in code.
Advantages :-
It does not require function calling overhead.
It also save overhead of variables push/pop on the stack, while function calling.
It also save overhead of return call from a function.
It increases locality of reference by utilizing instruction cache.
After in-lining compiler can also apply intra-procedural optimization if specified. This is the most important one, in this way compiler can now focus on dead code elimination, can give more stress on branch prediction, induction variable elimination etc..
To check more about it one can follow this link
http://tajendrasengar.blogspot.com/2010/03/what-is-inline-function-in-cc.html
I'd like to add that inline functions are crucial when you are building shared library. Without marking function inline, it will be exported into the library in the binary form. It will be also present in the symbols table, if exported. On the other side, inlined functions are not exported, neither to the library binaries nor to the symbols table.
It may be critical when library is intended to be loaded at runtime. It may also hit binary-compatible-aware libraries. In such cases don't use inline.
During optimization many compilers will inline functions even if you didn't mark them. You generally only need to mark functions as inline if you know something the compiler doesn't, as it can usually make the correct decision itself.
inline allows you to place a function definition in a header file and #include that header file in multiple source files without violating the one definition rule.
Generally speaking, these days with any modern compiler worrying about inlining anything is pretty much a waste of time. The compiler should actually optimize all of these considerations for you through its own analysis of the code and your specification of the optimization flags passed to the compiler. If you care about speed, tell the compiler to optimize for speed. If you care about space, tell the compiler to optimize for space. As another answer alluded to, a decent compiler will even inline automatically if it really makes sense.
Also, as others have stated, using inline does not guarantee inline of anything. If you want to guarantee it, you will have to define a macro instead of an inline function to do it.
When to inline and/or define a macro to force inclusion? - Only when you have a demonstrated and necessary proven increase in speed for a critical section of code that is known to have an affect on the overall performance of the application.
It is not all about performance. Both C++ and C are used for embedded programming, sitting on top of hardware. If you would, for example, write an interrupt handler, you need to make sure that the code can be executed at once, without additional registers and/or memory pages being being swapped. That is when inline comes in handy. Good compilers do some "inlining" themselves when speed is needed, but "inline" compels them.
Fell into the same trouble with inlining functions into so libraries. It seems that inlined functions are not compiled into the library. as a result the linker puts out a "undefined reference" error, if a executable wants to use the inlined function of the library. (happened to me compiling Qt source with gcc 4.5.
Why not make all functions inline by default? Because it's an engineering trade off. There are at least two types of "optimization": speeding up the program and reducing the size (memory footprint) of the program. Inlining generally speeds things up. It gets rid of the function call overhead, avoiding pushing then pulling parameters from the stack. However, it also makes the memory footprint of the program bigger, because every function call must now be replaced with the full code of the function. To make things even more complicated, remember that the CPU stores frequently used chunks of memory in a cache on the CPU for ultra-rapid access. If you make the program's memory image big enough, your program won't be able to use the cache efficiently, and in the worst case inlining could actually slow your program down. To some extent the compiler can calculate what the trade offs are, and may be able to make better decisions than you can, just looking at the source code.
Our computer science professor urged us to never use inline in a c++ program. When asked why, he kindly explained to us that modern compilers should detect when to use inline automatically.
So yes, the inline can be an optimization technique to be used wherever possible, but apparently this is something that is already done for you whenever it's possible to inline a function anyways.
Conclusion from another discussion here:
Are there any drawbacks with inline functions?
Apparently, There is nothing wrong with using inline functions.
But it is worth noting the following points!
Overuse of inlining can actually make programs slower. Depending on a function's size, inlining it can cause the code size to increase or decrease. Inlining a very small accessor function will usually decrease code size while inlining a very large function can dramatically increase code size. On modern processors smaller code usually runs faster due to better use of the instruction cache. - Google Guidelines
The speed benefits of inline functions tend to diminish as the function grows in size. At some point the overhead of the function call becomes small compared to the execution of the function body, and the benefit is lost - Source
There are few situations where an inline function may not work:
For a function returning values; if a return statement exists.
For a function not returning any values; if a loop, switch or goto statement exists.
If a function is recursive. -Source
The __inline keyword causes a function to be inlined only if you specify the optimize option. If optimize is specified, whether or not __inline is honored depends on the setting of the inline optimizer option. By default, the inline option is in effect whenever the optimizer is run. If you specify optimize , you must also specify the noinline option if you want the __inline keyword to be ignored. -Source
There's two things about inlining:
The inline keyword will be ignored if the compiler determines that the function cannot be inlined.
There is a compiler optimization (on Visual Studio, I don't know about GCC) that tells the compiler to inline all functions where possible.
From this I conclude that I never need to bother about inlining. I just have to turn on the compiler optimization for the release build.
Or are there any situations where manually inlining would be preferred?
The inline keyword has two functions:
it serves as a hint to the compiler to perform the inlining optimization (this is basically useless on modern compilers, which inline aggressively with or without the keyword)
it tells the compiler/linker to ignore the One Definition Rule: that the inline'd symbol may be defined in multiple translation units (typically because it is defined in a header, that is included from multiple files). Normally, this would result in a linker error, but it is allowed when you use the inline keyword.
Yes, if you want to put a function in a header file, and include that file in several translation units. This is in fact the main purpose of inline in C++.
Manual use of inline might be useful on older compilers or less sophisticated compilers (such as compilers for embedded development). If you're using visual studio, I don't think you typically need to use the inline keyword at all.
Inline is also useful if you want the ability to inline functions from a library. Only by putting the code for the function in the header file (which requires inline), is the compiler able to inline the function. Of course it is still up the the compiler whether to inline the function or not.
There's a side effect of inline keyword when you are building shared library. Inlined functions are not exported into symbol table nor into library's binary. As a result inline keyword is crucial in aspect of shared libraries, since compiler won't be able to inline exported function. On the other hand library's inline function will be always inlined because it doesn't exist in the binary form of the library.
You may not want to inline everywhere it is possible. This could increase the size of your binaries too much. You may have a select few functions that aren't used very much that inlining would allow to run faster without increasing the size of your bits significantly
It depends on your environment and what you want to do, so it is really hard to say when inlining is preferrable.
This link has some interesting reading about inlining. And some sound advice (which pretty much boils down to: avoid doing it)
Read Herb Sutters comments on inline:
http://www.gotw.ca/gotw/033.htm