6

How can I get the size of a function in C++?

Let's say I have a function:

void f()
{
/*do something*/
}

...By "size of f", I mean the size of the code /*do something*/, starting from the address indicated by a pointer to f.

Shog9
  • 156,901
  • 35
  • 231
  • 235
x1234x
  • 199
  • 1
  • 2
  • 4
  • 1
    Do you mean code length or size in memory? – moinudin Jan 02 '11 at 17:38
  • 7
    What size exactly? The C++ source code size or the resulting machine code size? What is the purpose at all? – Flinsch Jan 02 '11 at 17:38
  • 2
    @x1234x: you're gonna want to clarify what you actually want to *do* with this... As several answers have noted, the *size in bytes* is almost certainly impossible to retrieve reliably, and for many compilers probably meaningless even if you can determine it - but chances are, there's an easier and more reliable way to get what you want without this. – Shog9 Jan 02 '11 at 17:48
  • 1
    some day i made a "count lines of functions in file" script. See http://codepad.org/Nyutw95Z – Johannes Schaub - litb Jan 02 '11 at 17:52
  • @Kos: in practice, the reason I've wanted to know this *kind* of thing before is when optimizing embedded code for binary size. As with any optimization, before you start you want to know what functions account for the bulk of the thing you're trying to reduce. It just might be difficult in C++ to analyse this at the level of single functions. – Steve Jessop Jan 02 '11 at 17:56
  • @Steve Jessop, okay, but... a *runtime* check...? – Kos Jan 02 '11 at 18:41
  • @Kos: I'm not sure whether the questioner is actually asking for a runtime check, or just mentioning the runtime concept of the address of f as a way to explain what's wanted. If you asked for a way to determine the size of a `double` variable instead of a function, "starting from the address indicated by a pointer", that wouldn't imply a runtime measurement :-) – Steve Jessop Jan 02 '11 at 21:24
  • If a function is inlined, or is always called with constants which can be calculated at compile time, there may well not be a function to get the size of! – AshleysBrain Jan 02 '11 at 21:58
  • http://stackoverflow.com/questions/11410037/how-to-get-the-size-of-a-c-function – FrankH. Nov 22 '12 at 09:34
  • I had the same question and was able to get my function size in a Windows x64 binary. [Here's the details.](https://stackoverflow.com/a/48718199/670017) – ahmd0 Feb 10 '18 at 07:18

8 Answers8

15

You can't. It may not even be a well-defined concept. For example, consider the following code:

int f(int a) {
    return (3*a)+1;
}

int g(int a) {
    return (2*a)+1;
}

I doubt it happens in practice for this particular example, because it wouldn't be an optimization, but the compiler is permitted to introduce a block of code that computes a+1 then returns, and jump to that block from each of the entry points of f and g (after doing a multiplication in each case). What then would be the size of f? Should it include the size of the shared block? Half that size? It just doesn't make sense in C++ terms to claim that the function f has a size.

Also, a "pointer to f" may not simply be the address of the function f. It certainly provides a way to get to the entry point of f, but for example on an ARM processor in interworking mode, a pointer to a function consisting of Thumb code is actually the address of the first instruction, plus 1. In effect, the lsb of the pointer is masked off by the CPU when performing the jump to the function, but that bit tells the CPU to switch into Thumb mode rather than ARM mode. So the value of the pointer is not the address of the function (although it's close). Anyway, the entry point of a function need not necessarily be the at the start of it - if your compiler creates constant pools or similar, they could precede the executable code.

There may be platform-specific ways of examining your executables (either the files, or after loading into memory, or both), and saying what code is associated with what C++ functions. After all, it's what debug info is for. But there's no way of doing that in standard C++, and the standard doesn't require that any such mechanism exists.

Steve Jessop
  • 273,490
  • 39
  • 460
  • 699
4

Well, technically I don't believe you can, not portably.

But practically you may well be able to do this:

void f() { ... }
void g() { ... }

char *fp = (char *)&f;
char *gp = (char *)&g;

int size = gp - fp;

You're kind of relying on the compiler to put 'g' after 'f' in the object file, and that the linker followed suit, placing g after f.

Then you're just subtracting the pointers to get the difference.

There will likely be padding and other possible issues involved as well, so it may not be "exactly" the size of the function.

Will Hartung
  • 115,893
  • 19
  • 128
  • 203
  • 7
    I would be prepared to get quite random results with that – Roman L Jan 02 '11 at 18:15
  • 1
    I don't think there's anything preventing the linker from putting g before f, or very far away from f, then you get junk for the size. – AshleysBrain Jan 02 '11 at 21:59
  • 1
    Yup, there's a lot of room for this to go completely wrong, and I certainly wouldn't rely upon it in any portable way, but if it happens to work on your platform with your compiler, then hallelujah. – Will Hartung Jan 02 '11 at 23:25
3

Most compilers have an option to output assembly. Do that, look up the instructions in your processor's documentation and do the math.

Benjamin Lindley
  • 101,917
  • 9
  • 204
  • 274
1

With a text editor and wc? :) It's still not clear you mean by the size of a function, but I'd assume you mean the size of the machine code of the function. There's no way to do it, especially one portable across compilers. Many compilers would simply convert the program to assembly, so they don't know the size of the machine code.

At best, you could put a function after it and subtract the addresses, hoping that they would occupy consecutive and continuous parts of the memory, but there's really no guarantee that the compiler would do that.

Rosh Oxymoron
  • 20,355
  • 6
  • 41
  • 43
1

I suggest you do something like strlen except you use return opcode instead of zero as terminator.

Pyjong
  • 3,095
  • 4
  • 32
  • 50
  • 2
    Functions can have multiple return statements. – SLaks Jan 02 '11 at 17:44
  • 1
    Yes but they are usualy compiled as short jumps, leaving the function with one return instruction only. – Pyjong Jan 02 '11 at 17:59
  • @stupid_idiot: That would depend on the ABI. Some ABIs require the function to clean up its own stack, others require the callee to do that. – greyfade Jan 02 '11 at 19:14
  • 1
    I see what you have on mind but I don't quite get how does this influence the functionality of ret terminated strlen for the purpose of measuring size or compilation of multiple return statements in a function. the function stil ends with ret whether it has to clean the stack or not... – Pyjong Jan 02 '11 at 20:03
  • @stupid_idiot: A function ends with its last ret, not its first. But what is its last ret, especially if there are calculated branches? – MSalters Jan 03 '11 at 12:03
  • 1
    As I already said, these branches with returns are compiled as short jumps to the only ret in the whole function. Also, these jumps are preceded with storing a value into eax register which is deemed to hold the return value. – Pyjong Jan 03 '11 at 12:59
1

You can do that pretty easily if you are OK with changing the original function. You can change your function to look like that:

void f()
{
  /* do something */

  { volatile unsigned int _ = 0xBAD0BEEF; }
}

size_t getFunctionSize() {
  auto p = (char*)&f;

  // get close to the functions end
  while(*(unsigned int*)p != 0xBAD0BEEF) p++; 
  // dont forget to skip our constant
  p += sizeof(unsigned int);
  // loop until you find ret/retn (0xC3 and 0xC2 on x86)
  while(*p != 0xC3 && *p != 0xC2) p++;
  // note that you should add additional 2 bytes for retn
  if(*p == 0xC2) p += 2;

  return ((size_t)p - (size_t)&f);

}

Note that any destructors could, in theory, trigger the loop finding the ret/retn instructions.

Above code was not tested and it has been written from my memory, so it might be wrong, but that is a working design.

Artemking4
  • 31
  • 7
0

I want to get the size of the generated code in bytes so I can Copy the code to a new locatio and execute it from there . I know this is posible because i done it usig the 2 function and substraction method void f() { ... } void g() { ... }
char *fp = (char *)&f; char *gp = (char *)&g;
int size = gp - fp; and it worked in visual studio in release mode . The reason why I put this question is because I still have some problem with compiler optimizations , and I need a more secure mothod.

x1234x
  • 1
  • 1
0

Functions do not have "a size". As far as C++ is concerned, they are not objects and they do not take any storage space. In practice of course they exist as execution instructions in your resultant executable binary.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055