C函数内存分配
在C中,什么时候分配了一个函数,以及内存中的哪个地方去了?
当程序首先编译时分配函数的内存,还是先分配函数调用时分配的内存? 它是在堆栈上还是在代码段中分配的?
C函数的内存始终在函数加载到内存时从代码段中分配。 如果函数属于动态链接库,程序可能会在任意时间加载和卸载它。
你的问题是一个很好的问题,但是要做好一些额外的复杂性准备工作,因为这些东西中的一部分触及运行代码的CPU中的裸晶体管。
我选择尝试将它凝聚成4种类型,
代码存储应该是非常直接的,所以我会稍微复杂一点:将一群思想翻译成程序语言片段,此后称为“函数”,被翻译成一系列机器指令。
那些需要由处理器提取和执行的,所以它必须放在ROM或RAM中......定义一个代码存储区域。 即使该函数被多次或甚至递归调用,其代码也只有一个实例。
(让我们不要陷入困境)
全局数据存储器是所有非函数声明变量都可以生存的RAM(每个声明只有一个实例),以及声明为静态(在函数内外)的那些内存。 这些被绝对(或准)地址引用。
常量可能会或可能不会得到他们自己的ROM存储区......特定于其编译器/优化。
函数的本地存储是参数/返回传递和局部变量(在其中声明,因此只能由其可见)的函数,并且对函数的每次调用都需要一个单独的包,以便每次调用都可以获得单独的上下文。
通常(有令人难忘的例外),我们使用Call-Stack机制来堆积每个函数调用产生的多个本地存储区域。 这是越来越不确定,但你会发现这是一个堆栈框架,增加内存地址的减少。
因此,本地存储是编译器函数调用代码(为您自动完成的)放置函数的参数,被调用函数的返回占位符,调用函数的返回地址以及所有非静态(并优化为内部注册使用)变量。 每次呼叫一个。 引用这些局部变量和参数的函数代码将...... err ..通过堆栈指针加上一个偏移量,一个指向当前栈帧结束地址的CPU寄存器来引用后者(函数代码怎么样否则知道内存地址?)。
调用一个函数包括设置它的本地存储,最终将参数拷入(推入堆栈)并初始化一些本地数据,然后跳转到函数代码。 正在返回的是将被调用函数的返回值复制到调用者函数本地存储器中,销毁被调用的本地存储器,将堆栈指针放在先前堆积的本地存储包的末尾,然后跳转到保存的调用者下一个指令地址(弹出的东西)。 全做完了。
通过查看单个C进程的内存快照,您可以创建一个堆栈,其中包含多个有底堆积的本地存储区域,可以根据特定程序执行的函数调用/返回模式来阻止增长和缩减。
动态内存通常由malloc和free来管理:通过指针访问的内存块的增长地址堆栈的管理者。 这形成了一个错误命名的Heap区域(因为你很可能会得到一个瑞士cheesse,而不是堆)。
这些内存块可以用于任何目的,而挑战是确保一个人不会忘记释放它们,否则就会及时“泄漏”到调用堆栈中(容易看到这将是多么具有破坏性)。
它需要一些额外的训练来使用由malloc / free管理的动态内存,但是对于避免巨大的本地或浪费的全局存储非常有用(在函数需要处理一堆数据并且可以被调用几次的情况下,或者很少需要存储在内存中的大量数据)。
Dyn内存区域通常夹在全局和堆栈之间......一些嵌入式编译器会让您指定两者的大小。
Malloc和free并不是管理动态内存的唯一方法,而且我目前使用的是自制的反向引用分配器,它不需要free()。 没有纪律的代码和没有泄漏.... yaayy!
内联函数...
伟大的解释...
我想提供有关内联函数的内存分配的详细信息,这不包括在内。 内联函数可以被认为是一个宏,其中对函数的调用被代码替代,并且也进行参数评估。 在函数之前给内联关键词提供内联函数并不需要它,它只是建议编译器这是内联的候选者。 编译器最终选择这是否可以是内联函数。 因此内存分配将类似于一个函数。
链接地址: http://www.djcxy.com/p/79901.html上一篇: C function memory allocation
下一篇: In which segment is memory for library functions allocated?