最近我发布了一个问题:"Do functions occupy memory space?"
我得到的最好答案是:
是的,函数占用内存空间,但其大小完全取决于函数。
现在我不是在问他们占用的确切金额,但是这个函数占用了内存空间是什么?
例如: -
void demo()
{ }
上面的函数编译没有任何错误,但是这个函数完全是空的,它甚至没有return
语句。那么,占用内存空间的是什么功能呢?
答案 0 :(得分:4)
编辑:感谢Pascal的评论,这确实是正确的!由于这个原因,我改变了答案。
使用除none之外的任何优化设置,如果静态定义,即编译单元的本地,编译器将优化该函数。如果没有打开优化,它可能不会。在这种情况下,function prologue and epilogue,即在进入函数时设置堆栈帧等的代码,并在离开时销毁它,可能仍然由编译器发出。
正如Pascal指出它有外部链接时,这是不可能的,因为编译器通常不会跨模块“到达”。但是,在这种情况下,如果链接器检测到函数未被调用,则链接器应该优化它。
还可以完全确定函数占用的内存量。您可以查看包含该函数的对象的elfdump / objdump或类似的实用程序:)
回答你的问题
如果调用该函数,那占用内存空间的是什么?
必须将函数编译为machine code。这是驻留在内存中的依赖于体系结构的长度/值等的一组指令。计算机从内存中获取指令。因此,您的函数必须驻留在内存中的某个位置,以便CPU能够获取它然后执行它。您的写入的C代码被编译到此机器代码中,这就占用了内存空间......
答案 1 :(得分:1)
编译器通常会在优化时跳过此功能。所以答案是没有内存可以保留调用空函数。
答案 2 :(得分:1)
如果我们忽略编译器可能会或者可能不会优化函数,那么函数占用的内存会有很多种。
每次调用函数时,程序很可能必须将各种CPU寄存器存储在堆栈中,例如status/condition code register等寄存器。此外,程序计数器将存储在堆栈中,或者一旦功能执行完毕,CPU将不知道返回的位置。
保存的寄存器类型,位置和方式取决于系统。在程序中遇到“执行功能”指令时,CPU可能会自动执行大量此操作。
如果有任何参数或返回值,它们也将存储在堆栈/寄存器中。在这种情况下,它们可能由调用者或函数保存,它是系统特定的,称为calling convention。
除了上述内容之外,作为函数体的实际代码当然也存储在某个地方:程序存储器(通常称为.text
)。
答案 3 :(得分:1)
假设编译器没有省略给定的函数,因为它什么都不做。并假设编译器也不会内联它,因为函数很小。你的断言函数没有做任何事情,不会调用另一个函数,没有局部变量,也没有调用和返回值 - 那么为什么会需要任何内存?
首先,函数占用的大小将位于两个位置。一,在生成的二进制(可执行),第二,在调用此函数的线程的调用堆栈中。空函数有点像零字节文件或目录。两个貌似都不会占用磁盘中的任何存储空间(因为它显示为“0字节”)。但是,他们需要一些内存就是磁盘。
空文件的类比与空函数不完全相同,只是为了理解目的,我写道。函数将由某个函数(调用者)调用,因此该函数的 return-address 将保留在调用堆栈(当前线程)中。当函数不再存在时,将查找该返回地址,ESP将指向该位置以供下一条指令使用。
调用约定还会为空函数添加更多指令以清理调用堆栈。例如,Pascal调用约定会在函数退出时有更多指令来清理调用堆栈。
程序的位(32位或64位)也会改变所有这本书所需的大小。