代码之家  ›  专栏  ›  技术社区  ›  Thomson

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

c
  •  16
  • Thomson  · 技术社区  · 14 年前

    我想知道运行时C函数(由我编写)的长度。有什么方法可以得到它吗?看来Sizeof在这里不起作用。

    11 回复  |  直到 14 年前
        1
  •  14
  •   James McNellis    14 年前

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

        2
  •  17
  •   Clocks    12 年前

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

     nm -S <object_file_name>
    

    这将返回对象文件中每个函数的大小。请参阅GNU中的手册页,使用“man-nm”来收集更多关于这方面的信息。

        3
  •  13
  •   FazJaxton    11 年前

    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工具链都应该有一种方法来指定将函数分配给哪个部分。我将对照程序集列表检查结果,以验证它是否按您希望的方式工作。

        4
  •  4
  •   Vovanium    14 年前

    可执行文件(至少那些删除了调试信息的文件)不会以任何方式存储函数长度。所以不可能在运行时自己解析这些信息。如果必须使用函数进行操作,那么应该在链接阶段对对象进行一些操作,或者通过从可执行文件中将其作为文件进行访问。例如,您可以告诉链接器将符号表作为普通数据节链接到可执行文件中,为它们指定一些名称,并在程序运行时进行解析。但请记住,这是特定于链接器和对象格式的。

    另外,请注意,功能布局也是平台特定的,有些事情会使术语“功能长度”变得不清楚:

    1. 函数可以在函数代码后直接将使用过的常量存储在代码段中,并使用PC相对寻址(ARM编译器这样做)。
    2. 函数可以有“prologs”和“epilogs”,这可能是多个函数共同的,因此位于主体之外。
    3. 函数代码可以嵌入其他函数代码

    它们都可以在函数长度中计数,也可以不计数。

    函数也可能完全由编译器内联,因此它会失去主体。

        5
  •  3
  •   Sam Skuce    14 年前

    在例如codewarrior中,可以在函数周围放置标签,例如

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

    然后计算尺寸 (int)(label2-label1) 但这显然是非常依赖于编译器的。根据您的系统和编译器,您可能需要黑客链接器脚本等。

        6
  •  3
  •   PierreG    14 年前

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

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

    #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之前实现了main),那么您将得到一个不相关的(负的)计算,让您知道它不是这样工作的,但是如果您将foo()代码移到main()中,它将工作-只需用初始的负r减去得到的main()大小即可。埃普利

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

    结束(int)(long)强制转换用于32位和64位代码之间的可移植性(64位平台上的函数指针将更长)。

    这是故障便携式的,应该工作得相当好。

        7
  •  1
  •   John Bode    14 年前

    C语言本身没有定义返回函数长度的功能;只涉及太多变量(编译器、目标指令集、对象文件/可执行文件格式、优化设置、调试设置等)。对于不同的系统,相同的源代码可能会产生不同大小的函数。

    C只是不提供任何反射能力来支持这种信息(尽管个别编译器可能提供扩展,例如sskuce引用的代码战士示例)。如果您需要知道您的函数在内存中占用了多少字节,那么您必须直接检查生成的对象或可执行文件。

    sizeof func 不起作用,因为表达式 func 被视为指向函数的指针,所以您得到的是指针值的大小,而不是函数本身。

        8
  •  1
  •   Vad    8 年前

    只需从下一个函数的地址中减去函数的地址。但是请注意,它可能在您的系统上不起作用,因此只有在您 是否100%确定:

    #include <stdint.h>
    
    int function() {
        return 0;
    }
    
    int function_end() {
        return 0;
    }
    
    int main(void) {
        intptr_t size = (intptr_t) function_end - (intptr_t) function;
    }
    
        9
  •  1
  •   Gurhan Polat    6 年前

    我刚刚为完全相同的问题提出了一个解决方案,但是我编写的代码依赖于平台。

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

        10
  •  0
  •   Armen Tsirunyan    14 年前

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

        11
  •  -3
  •   vpatial    11 年前

    您可以通过减去函数的地址来找到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;
    }
    

    希望你编完后能得到答案。编译之后,您将能够看到 函数01和函数2的大小不同。

    注意:通常一个函数和另一个函数之间有16个字节的差异。