如何以字节为单位获取函数的长度?

时间:2010-11-11 16:20:50

标签: c

我想在运行时知道C函数的长度(由我编写)。任何获得它的方法?似乎sizeof在这里不起作用。

11 个答案:

答案 0 :(得分:17)

有一种方法可以确定函数的大小。命令是:

 nm -S <object_file_name>

这将返回目标文件中每个函数的大小。使用'man nm'查阅GNU中的手册页以收集更多相关信息。

答案 1 :(得分:14)

标准C中无法获取函数占用的内存量。

答案 2 :(得分:13)

如果使用自定义链接描述文件,则可以从链接器获取此信息。仅为给定函数添加链接器部分,并在任一侧添加链接器符号:

mysec_start = .;
*(.mysection)
mysec_end = .;

然后您可以专门将该功能分配给该部分。符号之间的差异是函数的长度:

#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;
}

此示例适用于GCC,但任何C工具链都应该有一种方法来指定要为其分配函数的部分。我会根据汇编列表检查结果,以验证它是否按照您希望的方式工作。

答案 3 :(得分:4)

可执行文件(至少已剥离调试信息的文件)不以任何方式存储函数长度。因此,不可能在运行时通过self解析此信息。如果必须使用函数进行操作,则应在链接阶段对象或从可执行文件中将文件作为文件访问。例如,您可以告诉链接器将符号表作为普通数据部分链接到可执行文件中,为它们分配一些名称,并在程序运行时进行解析。但请记住,这将特定于您的链接器和对象格式。

另请注意,功能布局也是特定于平台的,并且有些事情使“功能长度”一词不明确:

  1. 函数可以在函数代码之后直接在代码段中存储使用的常量,并使用PC相对寻址访问它们(ARM编译器执行此操作)。
  2. 功能可能有“prologs”和“epilogs”,它们可能是多个功能共有的,因此位于主体之外。
  3. 功能代码可以内联其他功能代码
  4. 他们都可以计算或不计算函数长度。

    此外,函数可能会被编译器完全内联,因此它会松散它的主体。

答案 4 :(得分:3)

例如Codewarrior,您可以在函数周围放置标签,例如

label1:
void someFunc()
{
    /* code goes here. */
}
label2:

然后像(int)(label2-label1)那样计算大小,但这显然与编译器有关。根据您的系统和编译器,您可能必须破解链接器脚本等。

答案 5 :(得分:3)

函数的开头是函数指针,你已经知道了。

问题是找到结束,但可以这样做:

#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);
}

它在这里工作,因为程序只有两个函数,所以如果代码重新排序(主要在foo之前实现)那么你将得到一个无关的(负面)计算,让你知道它不是这样工作但是那个如果你将foo()代码移动到main()中它会工作 - 只需减去初始否定回复所带来的main()大小。

如果结果是肯定的,那么它将是正确的 - 如果没有填充(是的,一些编译器愉快地膨胀代码,无论是为了对齐还是为了其他不太明显的原因)。

结束(int)(long)强制转换是为了在32位和64位代码之间实现可移植性(64位平台上的函数指针会更长)。

这是便携式的,应该可以很好地工作。

答案 6 :(得分:1)

在C语言本身中没有定义任何工具来返回函数的长度;涉及的变量太多(编译器,目标指令集,目标文件/可执行文件格式,优化设置,调试设置等)。完全相同的源代码可能导致不同系统的不同大小的功能。

C根本不提供任何类型的反射功能来支持这种信息(尽管个别编译器可能提供扩展,例如sskuce引用的Codewarrior示例)。如果您需要知道函数占用内存的字节数,那么您必须直接检查生成的对象或可执行文件。

sizeof func将无效,因为表达式func被视为指向函数的指针,因此您获得指针值的大小,而不是函数本身。

答案 7 :(得分:1)

我刚刚针对完全相同的问题提出了解决方案,但我编写的代码取决于平台。

背后的想法是,将已知操作码放在函数的末尾,并在计算我们已跳过的字节的同时从头开始搜索它们。 这是我用一些代码解释的媒体链接 https://medium.com/@gurhanpolat/calculate-c-function-size-x64-x86-c1f49921aa1a

答案 8 :(得分:0)

在C或C ++中没有标准的方法。可能自然存在实现/平台特定的doiung方式,但我不知道任何

答案 9 :(得分:0)

如果你是为 x86 编译,你可以试试这个

 int GetFuncSizeX86(unsigned char* Func)
 {
 if (!Func)
     return 0;

 // printf("Getting the Function Size on ===> %08X\n", Func);
 int count = 0;
  KeepCount:
 while (*Func != 0xC3)
 {
     //printf("Current Opcode ==> %01X\n", *Func);
     Func++;
     count++;
 }

 //printf("C3 Opcode Found\n");

 //printf("Back Opcode ==> %01X\n", *(Func - 1));

 //printf("Next Opcode ==> %01X\n", *(Func + 1));
 if (*(Func + 1) == 0xCC
     || *(Func - 1) == 0x5D
     || *(Func - 1) == 0x5B
     || *(Func - 1) == 0x5E
     || *(Func - 1) == 0x5F
     || *(Func - 1) == 0xCC
     || *(Func - 1) == 0xC9)
 {
     count++;
     return count;
 }
 else
 {
     Func++;
     count++;
     goto KeepCount;
 }
}

只需将函数强制转换为 char*

答案 10 :(得分:-3)

您可以通过减去函数的地址来找到C函数的长度。 让我举个例子

int function1()
    {
    } 

int function2()
{
    int a,b;    //just defining some variable for increasing the memory size
    printf("This function would take more memory than earlier function i.e function01 ");
}

int main()
{
    printf("Printing the address of function01 %p\n",function01);
    printf("Printing the address of function02 %p\n",function02);
    printf("Printing the address of main %p\n",main);
    return 0;
}

希望你在编译之后得到你的答案。编译后你就能看到了 function01和function2的大小差异。

注意:通常一个函数与另一个函数之间存在16字节差异。