我读了静态内存分配和动态内存分配的文档
静态内存分配是指在执行相关程序之前在编译时保留内存的过程,这与在运行时发生的动态内存分配不同。
我的问题是: -
如何在编译期间保留内存?
以示例为例
#include <stdlib.h>
void main()
{
int i;
}
以上代码是static memory allocation
的示例。
变量i
仅在运行期间(即程序执行期间)加载到内存中,然后在编译时如何将内存分配给它?
答案 0 :(得分:2)
将此程序编译为汇编时:
int i = 7;
int main()
{
return 0;
}
您可以看到全局变量i
位于“数据”部分,并且是静态分配的。
.globl _i
.data ## data section (for explicitly initialized global/static vars)
.align 2
_i: ## the global variable i
.long 7 ## is allocated here
.text
.globl _main
_main:
LFB0:
pushl %ebp
LCFI0:
movl %esp, %ebp
LCFI1:
movl $0, %eax
popl %ebp
LCFI2:
ret
LFE0:
.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
EH_frame1:
.set L$set$0,LECIE1-LSCIE1
.long L$set$0
LSCIE1:
.long 0
.byte 0x1
.ascii "zR\0"
.byte 0x1
.byte 0x7c
.byte 0x8
.byte 0x1
.byte 0x10
.byte 0xc
.byte 0x5
.byte 0x4
.byte 0x88
.byte 0x1
.align 2
LECIE1:
LSFDE1:
.set L$set$1,LEFDE1-LASFDE1
.long L$set$1
LASFDE1:
.long LASFDE1-EH_frame1
.long LFB0-.
.set L$set$2,LFE0-LFB0
.long L$set$2
.byte 0
.byte 0x4
.set L$set$3,LCFI0-LFB0
.long L$set$3
.byte 0xe
.byte 0x8
.byte 0x84
.byte 0x2
.byte 0x4
.set L$set$4,LCFI1-LCFI0
.long L$set$4
.byte 0xd
.byte 0x4
.byte 0x4
.set L$set$5,LCFI2-LCFI1
.long L$set$5
.byte 0xc4
.byte 0xc
.byte 0x5
.byte 0x4
.align 2
LEFDE1:
.subsections_via_symbols
答案 1 :(得分:1)
C中的对象可以具有三个存储持续时间之一:
具有静态存储持续时间的对象在程序启动时为它们分配了内存,并且在程序退出之前不会释放内存。这通常通过在程序图像本身内保留空间来完成; IOW,程序的二进制文件有一些保留用于常量(.rdata
或.rodata
)和非常量(.bss
)数据的部分。这是他们在编译时保留的意思;编译器在生成的二进制文件中留出部分用于数据存储。但是,在将程序加载到内存并运行之前,这些部分是不可用的。
具有 auto 存储持续时间的对象在程序进入其封闭范围时在运行时为其分配内存,并在程序退出该范围时释放。
给出以下代码:
void foo( void )
{
int x;
for ( x = 0; x < 100; x++ )
{
int y = x * 2;
...
}
}
按逻辑说话,当您输入x
函数并保持到foo
退出时foo
的空格将被搁置,y
的空格将被{当您进入for
循环时,{1}}将被放在一边,并在循环退出时释放。在实践中(至少在我熟悉的平台上),两者的空间将在函数入口处留出并在函数出口处释放,但你不应该假设{{1}的空间将在循环之外可用。
大多数系统使用堆栈来管理具有自动存储持续时间 1 的对象。
具有动态存储持续时间的对象通过调用库函数y
,malloc
或calloc
来保留其内存,并且该内存将保留到它是通过调用realloc
明确发布的:
free
变量void *foo( void )
{
void *mem = malloc( SOME_MEMORY );
...
return mem;
}
void bar( void )
{
void *data = foo();
...
free( data );
}
和mem
都有自动存储持续时间。 bar
仅存在于mem
中,且数据仅存在于foo
中。但是,它们指向的对象具有动态存储持续时间;它在bar
中分配,并持续到foo
中的explcitly发布。
这些对象的内存池通常称为&#34; heap&#34;。
<小时/> 1。 C最初是在使用堆栈管理运行时数据的系统上设计的,因此它是实现
bar
变量行为的自然方式。然而,语言定义是以容纳非基于堆栈的系统的方式编写的,尽管它们很难实现。
答案 2 :(得分:0)
编译代码时,编译器会决定为每个对象分配多少内存(比如变量或函数代码),它们将按顺序放在内存和地址中。当然,在程序启动之前可能不会创建变量,但是事先分配了内存,变量地址已经编译到代码中 - 例如i
变量地址被编译到i=7;
中指令。
修改强>
变量可以静态分配或动态分配,动态变量可以自动分配(在C / C ++中它们通常是函数中的局部变量,在堆栈或寄存器中创建)或“手动”,即是以可控制的方式(由malloc
或new
创建,由free
或delete
处理。静态变量存在于整个过程生命周期中,动态变量在需要时创建并在使用后销毁。
int fun( int param)
{
int automatic_var = 3;
return automatic_var + ++param;
}
int static_var = 7;
void main()
{
int automatic_var2;
automatic_var2 = fun( static_var);
}
在上面的代码中,automatic_var2
获得了分配值11
变量static_var
贯穿整个过程执行时间,
变量automatic_var2
在main()
执行时间内存在,
变量automatic_var
和param
仅在fun()
执行时间内存在。
有时,自动分配被认为是第三种方式,与自动动态分配分开。无论如何,函数内的int i;
声明,无论是否为动态声明,当然 static 分配(即使它是main()
,其执行时间几乎整个过程执行时间。)
答案 3 :(得分:0)
在C中有四种存储形式:
有些作者将这些分为静态和动态两类。每个人都同意静态是静态的,已分配是动态的,但您的示例是自动,因此将其分配给其他类别之一是随心所欲。使用标准术语对我来说似乎更清楚。
答案 4 :(得分:0)
无论静态和动态内存分配如何,程序只在执行时获取内存。
执行时会出现静态和动态的概念。当执行静态存储器时,在数据或代码段之一中分配。动态分配在你调用malloc或calloc时会发生,它会在堆中获取内存,只有当包含malloc或calloc的语句发生并且它们被称为动态时才会发生这种情况。
编译后的内存不像是在RAM上分配的。 在C中,静态和动态概念仅在程序执行时出现,否则没有为代码分配内存。