如何在C ++中获取函数的大小?
假设我有一个功能:
void f()
{
/*do something*/
}
...“f
的大小”是指代码/*do something*/
的大小,从指向f
的地址开始。
答案 0 :(得分:12)
你做不到。它甚至可能不是一个定义明确的概念。例如,请考虑以下代码:
int f(int a) {
return (3*a)+1;
}
int g(int a) {
return (2*a)+1;
}
我怀疑这个特定的例子在实践中发生了,因为它不是一个优化,但允许编译器引入一个计算a+1
然后返回的代码块,然后跳转到该块f
和g
的每个入口点(在每种情况下进行乘法后)。那么f
的大小是多少?它应该包括共享块的大小吗?那么大一半?声称函数f
具有大小。
此外,“指向f的指针”可能不仅仅是函数f的地址。它确实提供了一种到达f
入口点的方法,但是例如在交互模式下的ARM处理器上,指向由Thumb代码组成的函数的指针实际上是第一条指令的地址加1。实际上,当执行跳转到函数时,CPU会屏蔽指针的lsb,但该位会告诉CPU切换到Thumb模式而不是ARM模式。所以指针的值不是函数的地址(尽管它很接近)。无论如何,函数的入口点不一定是它的开头 - 如果你的编译器创建常量池或类似的,它们可以在可执行代码之前。
可能有特定于平台的方法来检查您的可执行文件(文件,或加载到内存后,或两者),并说明什么代码与C ++的功能相关联。毕竟,这是调试信息的用途。但是在标准C ++中没有办法做到这一点,标准不要求任何这样的机制存在。
答案 1 :(得分:4)
嗯,从技术上来说,我不相信你可以,而不是便携。
但实际上你可以做到这一点:
void f() { ... }
void g() { ... }
char *fp = (char *)&f;
char *gp = (char *)&g;
int size = gp - fp;
你有点依赖编译器在对象文件中的'f'之后添加'g',并且链接器也是如此,在f之后放置g。
然后你只是减去指针以获得差异。
也可能涉及填充和其他可能的问题,因此它可能不是“完全”函数的大小。
答案 2 :(得分:3)
大多数编译器都有输出程序集的选项。这样做,查看处理器文档中的说明并进行数学计算。
答案 3 :(得分:1)
使用文本编辑器和wc
? :)你还不清楚你的意思是函数的大小,但我假设你的意思是函数的机器代码的大小。没有办法做到这一点,特别是在编译器之间可移植。许多编译器只是简单地将程序转换为汇编程序,因此他们不知道机器代码的大小。
充其量,你可以在它之后放一个函数并减去地址,希望它们会占用内存的连续和连续部分,但实际上并不能保证编译器会这样做。
答案 4 :(得分:1)
我建议你做一些类似strlen的事情,除非你使用return opcode而不是零作为终结符。
答案 5 :(得分:0)
我想以字节为单位获取生成代码的大小,这样我就可以将代码复制到新的位置并从那里执行。我知道这是可行的,因为我使用了2函数和减法方法
void f(){...}
void g(){...}
char * fp =(char *)& f;
char * gp =(char *)& g;
int size = gp - fp;
它在发布模式下在visual studio中工作。
我提出这个问题的原因是因为我对编译器优化仍有一些问题,而且我需要一个更安全的方法。
答案 6 :(得分:-1)
功能没有“大小”。就C ++而言,它们不是对象,也不占用任何存储空间。实际上,它们在生成的可执行二进制文件中作为执行指令存在。