简体   繁体   中英

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

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 .

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.

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.

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

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.

我建议你做一些类似strlen的事情,除非你使用return opcode而不是零作为终结符。

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.

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM