68
votes

I want to force a little function not to be compiled as inline function even if it's very simple. I think this is useful for debug purpose. Is there any keyword to do this?

9
The debugger can handle inlined functions just fine. No need to prevent inlining because of that.jalf
Not really. Great way to hang the debugger for many minutes while it sets thousands of breakpoints.Hans Passant
When stepping through optimized code (which you basically have to do at the assembly language level) it's sometimes nice to see calls to functions sometimes so you can follow where you are, and step over them in one go -- since the compiler's view of "simple" may not be yours. (The debugger may cope fine with all of this, but it's the computer operator that has to actually do the work...)please delete me
In addition to debugging, I also wanted to do this for profiling purposes. A function was being inlined without me indicating that it should be. However, that was the specific function that I had wanted to see in the profile.Justin Peel
@thecoshman There are times where you have to debug release code, or you have dumps of release codeGhita

9 Answers

57
votes

In Visual Studio 2010, __declspec(noinline) tells the compiler to never inline a particular member function, for instance:

class X {
     __declspec(noinline) int member_func() {
          return 0; 
     }
};

edit: Additionally, when compiling with /clr, functions with security attributes never get inlined (again, this is specific to VS 2010).

I don't think it will prove at all useful at debugging, though.

56
votes

__declspec(noinline) for VC++. Contrary to the man page, this appears to work for freestanding functions, and I don't think I've ever used it for a member function. You may -- though note that I never have -- want to consider playing with the optimization flags too, so that only inline functions are considered for inlining, though of course this has a global effect and that may not be what you want.

__attribute__((noinline)) for gcc (and a number of less-common compilers that support the gcc attribute syntax). I must admit, I don't think I've ever actually used this, but it appears to be there.

(Of course, these two styles of annotation go in different places, so it's a bit annoying to construct code that's palatable to both.)

I'm not sure how either of these interact with the inline C++ keyword; I've only used them when debugging (when I just want a particular non-inline function left not inline after optimization) or when examining generated code (and I'm getting confused because random stuff is being inlined).

15
votes

Please remember that inlining is relevant at the function call site, the same function can be inlined in some situations and not inlined in other.

If your function is visible outside the compilation unit then even if it's inlined in all the current places it's used, the body of the function must still be available for anyone who wants to call it later on (by linking with the object file).

In order to have a call site not inlined you can use a pointer to a function.

void (*f_ptr)(int); // pointer to function
volatile bool useMe = true; // disallow optimizations 
if (useMe)
   f_ptr = myFunc;
else
   f_ptr = useOtherFunc;

f_ptr(42); // this will not be inlined
5
votes

Simple: Don't let the compiler see the definition of the function. Then it cannot possibly be inlined. Of course, that only works if its your code.

When it comes to debugging 3rd party code... yes, this would be useful, especially if you could zap 3rd party code from afar. Anyone who has debugged code that contains lot of shared_ptr dereferencing knows what I'm talking about.

5
votes

[[gnu::noinline]] attribute

We can also use the C++11 attribute specifier syntax with the non-standard gnu::noinline attribute: https://en.cppreference.com/w/cpp/language/attributes

It is just a matter of time until that gnu:: part gets dropped a future C++ standard to give a standardized [[noinline]] :-)

main.cpp

[[gnu::noinline]]
int my_func() {
    return 1;
}

int main() {
    return my_func();
}

Compile and disassemble:

g++ -ggdb3 -O3 -o main.out -std=c++11 -Wall -Wextra -pedantic-errors main.cpp
gdb -batch -ex 'disassemble/r main' main.out

With [[gnu::noinline]]:

   0x0000000000001040 <+0>:     f3 0f 1e fa     endbr64 
   0x0000000000001044 <+4>:     e9 f7 00 00 00  jmpq   0x1140 <my_func()>

Without [[gnu::noinline]]:

   0x0000000000001040 <+0>:     f3 0f 1e fa     endbr64 
   0x0000000000001044 <+4>:     b8 01 00 00 00  mov    $0x1,%eax
   0x0000000000001049 <+9>:     c3      retq

Tested on Ubuntu 19.10.

1
votes

Many compilers can perform cross-translation-unit inlining. Visual Studio has had it for five years and I believe that GCC can now do it- especially since the OP tagged as Visual C++, it's a fair bet that his compiler can cope.

The simplest way to do this is to take the function's address, and then do something non-meaningless with it, like call it or pass it to an OS/external library function. The compiler can't inline that kind of function.

Why you would ever want to, IDK.

@comments:

If the OP srsly, srsly needs this, then he could compile it as a lib and statically link to it.

1
votes

If it is a member function of a class, make it virtual.

0
votes

You can divide the class implementation between a header and cpp file. if you put the function outside of the class definition, your little function wont be inline.

-18
votes

Is it possible to force a function not to be inlined?

I won't even attempt to answer that question, because it's irrelevant to be concerned with this except for the two reasons outlined below.

Inlining basically is

  1. an optimization that's mostly transparent to you
  2. a way to allow functions to be defined in headers without getting multpile definition errors

(Some would switch the order of these two, but I stick to the traditional order.)

Unless either A) you absolutely need to define a function in some header or B) you are profiling and optimizing a piece of code and know better than the compiler what should be inlined and what shouldn't, inlining should be of no concern to you.
It certainly shouldn't be a concern because of debugging. Your debugger should (and in the case of VC also does) take care of that for you.