Clo*_*cks 19
有一种方法可以确定函数的大小.命令是:
nm -S <object_file_name>
Run Code Online (Sandbox Code Playgroud)
这将返回目标文件中每个函数的大小.使用'man nm'查阅GNU中的手册页以收集更多相关信息.
Faz*_*ton 14
如果使用自定义链接描述文件,则可以从链接器获取此信息.仅为给定函数添加链接器部分,并在任一侧添加链接器符号:
mysec_start = .;
*(.mysection)
mysec_end = .;
Run Code Online (Sandbox Code Playgroud)
然后,您可以专门将该功能分配给该部分.符号之间的差异是函数的长度:
#include <stdio.h>
int i;
__attribute__((noinline, section(".mysection"))) void test_func (void)
{
i++;
}
int main (void)
{
extern unsigned char mysec_start[];
extern unsigned char mysec_end[];
printf ("Func len: %lu\n", mysec_end - mysec_start);
test_func ();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
此示例适用于GCC,但任何C工具链都应该有一种方法来指定要为其分配函数的部分.我会根据汇编列表检查结果,以验证它是否按照您希望的方式工作.
可执行文件(至少是那些去除了调试信息的)不以任何方式存储函数长度。所以不可能在运行时自己解析这些信息。如果您必须使用函数进行操作,您应该在链接阶段对您的对象做一些事情,或者通过从您的可执行文件中访问它们作为文件。例如,您可以告诉链接器将符号表作为普通数据段链接到可执行文件中,为其分配一些名称,并在程序运行时进行解析。但请记住,这将特定于您的链接器和对象格式。
另请注意,该功能布局也是特定于平台的,并且有些事情使术语“功能长度”不清楚:
它们都可以计算或不计算函数长度。
函数也可能被编译器完全内联,所以它失去了它的主体。
小智 5
函数的开头是函数指针,你已经知道了。
问题是要找到终点,但这可以通过以下方式完成:
#include <time.h>
int foo(void)
{
int i = 0;
++i + time(0); // time(0) is to prevent optimizer from just doing: return 1;
return i;
}
int main(int argc, char *argv[])
{
return (int)((long)main - (long)foo);
}
Run Code Online (Sandbox Code Playgroud)
它在这里工作是因为程序只有两个函数,所以如果代码被重新排序(主要在 foo 之前实现)那么你将得到一个不相关的(负)计算,让你知道它不能以这种方式工作,但它会工作如果您将 foo() 代码移动到 main() 中 - 只需减去初始否定回复得到的 main() 大小。
如果结果是肯定的,那么它就是正确的——如果没有进行填充(是的,一些编译器很乐意膨胀代码,无论是为了对齐还是其他不太明显的原因)。
结尾的 (int)(long) 类型转换是为了 32 位和 64 位代码之间的可移植性(函数指针在 64 位平台上会更长)。
这是可移植性失败的,应该可以很好地工作。
小智 5
我刚刚为完全相同的问题想出了一个解决方案,但我编写的代码取决于平台。
背后的想法是,将已知的操作码放在函数的末尾并从头开始搜索它们,同时计算我们跳过的字节数。这是我用一些代码解释的中等链接 https://medium.com/@gurhanpolat/calculate-c-function-size-x64-x86-c1f49921aa1a
一个完全解决的解决方案,没有链接器或肮脏的平台相关技巧:
#include <stdio.h>
int i;
__attribute__((noinline, section("mysec"))) void test_func (void)
{
i++;
}
int main (void)
{
extern char __start_mysec[];
extern char __stop_mysec[];
printf ("Func len: %lu\n", __stop_mysec - __start_mysec);
test_func ();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这就是当您阅读FazJaxton 的答案和jakobbotsch 的评论时得到的结果