静态和动态分配内存

时间:2014-08-19 17:40:56

标签: c dynamic-memory-allocation static-memory-allocation

我读了静态内存分配和动态内存分配的文档

  

静态内存分配是指在执行相关程序之前在编译时保留内存的过程,这与在运行时发生的动态内存分配不同。

我的问题是: -

如何在编译期间保留内存?

以示例为例

#include <stdlib.h>
void main()
{
    int i;
}

以上代码是static memory allocation的示例。

变量i仅在运行期间(即程序执行期间)加载到内存中,然后在编译时如何将内存分配给它?

5 个答案:

答案 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 的对象。

具有动态存储持续时间的对象通过调用库函数ymalloccalloc来保留其内存,并且该内存将保留到它是通过调用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 ++中它们通常是函数中的局部变量,在堆栈或寄存器中创建)或“手动”,即是以可控制的方式(由mallocnew创建,由freedelete处理。静态变量存在于整个过程生命周期中,动态变量在需要时创建并在使用后销毁。

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_var2main()执行时间内存在,
变量automatic_varparam仅在fun()执行时间内存在。

有时,自动分配被认为是第三种方式,与自动动态分配分开。无论如何,函数内的int i;声明,无论是否为动态声明,当然 static 分配(即使它是main(),其执行时间几乎整个过程执行时间。)

答案 3 :(得分:0)

在C中有四种存储形式:

  • automatic(又名堆叠)
  • 螺纹
  • 静态
  • 已分配(又名堆)

有些作者将这些分为静态和动态两类。每个人都同意静态是静态的,已分配是动态的,但您的示例是自动,因此将其分配给其他类别之一是随心所欲。使用标准术语对我来说似乎更清楚。

答案 4 :(得分:0)

无论静态和动态内存分配如何,程序只在执行时获取内存。

执行时会出现静态和动态的概念。当执行静态存储器时,在数据或代码段之一中分配。动态分配在你调用malloc或calloc时会发生,它会在堆中获取内存,只有当包含malloc或calloc的语句发生并且它们被称为动态时才会发生这种情况。

编译后的内存不像是在RAM上分配的。 在C中,静态和动态概念仅在程序执行时出现,否则没有为代码分配内存。