2014-02-13 43 views
0

最近我发布了一个问题:"Do functions occupy memory space?"
最好的答案,我得到的是:函数中占用内存空间的是什么?

是,该功能占用内存空间,但是它的大小完全取决于功能。

现在我不问他们占用的确切数量,但是函数中占用内存空间的是什么?

为〔实施例: -

​​

上述功能编译没有任何错误,但这个功能完全是空的,它是不是有连return声明。那么,占用这个功能的内存空间是什么?

+2

一个好的编译器应该优化和删除这个函数,即使你调用它。但是假设如果你打印deom的地址,那么函数定义将存在于可执行文件中。 –

回答

4

编辑:谢谢Pascal他的评论这确实是正确的!因此,我已经改变了答案。


使用任何优化设置比没有其他,编译器会优化该函数远离,如果它是静态定义即本地到此编译单元。没有优化打开它可能不会。在这种情况下,function prologue and epilogue,它们是在进入函数时设置堆栈帧等并在离开时破坏它的代码,可能仍会由编译器发出。

由于Pascal指出,当它有外部链接时,这是不可能的,因为编译器通常不会跨越模块“达到”。但是,在这种情况下,如果链接器检测到该函数未被调用,则应该优化它。

此外,完全可以确定函数占用了多少内存。你可以看一下elfdump/objdump或类似的适当的工具,用于包含函数:)


要回答你的问题

如果函数被调用的对象,那么什么是占用内存空间?

函数必须被编译成machine code。这是一组驻留在内存中的与体系结构有关的长度/值等的指令。计算机从内存中获取指令。因此,您的函数必须驻留在内存中的某处,以便CPU能够获取并执行它。你写的C代码被编译到这个机器代码中,这就占用了内存空间...

+3

“使用除none以外的任何优化设置,编译器应该优化此功能”绝对不是。一个函数'demo'具有外部链接。它不能被编译器删除。 –

+0

是非常好的一点,谢谢大家指出,+1 – Jimbo

+0

@Jimbo:如果函数被调用,那么占用内存空间是什么? –

1

编译器通常会在优化时跳过这个函数。所以答案是没有内存将保留调用一个空函数。

1

如果我们忽略编译器可能会或可能不会优化功能,那么函数占用的内存有很多种。

每次调用某个函数时,程序都可能需要将各种CPU寄存器存储在堆栈中,例如status/condition code register等寄存器。此外,程序计数器将被存储在堆栈中,或者一旦该函数完成执行,CPU就不知道该返回到哪里。

什么样的寄存器被保存,以及在哪里以及如何取决于系统。在程序中遇到“执行功能”指令时,CPU可能会自动执行很多操作。

如果有任何参数或返回值,它们也将被存储在堆栈/寄存器中。在这种情况下,它们可以由呼叫者或功能保存,它是系统特定的并且被称为calling convention

除上述之外,作为函数主体的实际代码当然也存储在某处:程序存储器中(通常称为.text)。

1

让我们假设编译器不会省略给定的函数,因为它什么都不做。并且假定编译器不会内联它,因为函数很小。你的断言函数不做任何事情,不调用另一个函数,没有局部变量,也没有参数和返回值 - 那为什么需要任何内存?

第一件事,函数占用的大小将在两个位置。一个是生成的二进制文件(可执行文件),另一个是调用该函数的线程的调用堆栈。一个空函数有点像零字节文件或目录。 看似不占用磁盘中的任何存储(因为它显示为'0字节')。但是,他们需要一些内存是磁盘。

空文件的类比与空函数不完全相同,只是为了理解目的,我写了。函数会被某个函数(调用者)调用,因此该函数的返回地址将被保存在当前线程的调用堆栈中。当函数停止存在时,将返回该地址,并且ESP将指向下一条指令的该位置。

调用约定也会为空函数添加更多指令来清理调用堆栈。例如,Pascal调用约定在函数退出时会有更多的指令来清理调用堆栈。

程序的位数(32位或64位)也会改变所有簿记所需的大小。

相关问题