【问题标题】:static and dynamic allocation of memory内存的静态和动态分配
【发布时间】:2014-10-12 22:10:17
【问题描述】:

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

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

我的问题是:-

如何在编译时保留内存?

举个例子

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

上面的代码是static memory allocation的一个例子。

变量i只会在运行时加载到内存中,即程序执行期间,那么在编译时如何分配内存呢?

【问题讨论】:

  • The above code is an example of static memory allocation 实际上,没有。 i 的内存是从堆栈中分配的。
  • @FiddlingBits:然后呢?
  • 错了,这是动态(准确地说是自动)分配的变量。静态分配发生在这里:int i; void main(){ i=7; }
  • 字符串字面量也是静态分配的; char* some_str = "hello, world!" 加载到与堆栈和堆完全不同的内存部分。
  • @kevingomes i 的内存取自静态内存,但i 是一个自动变量,因此,内存不必一直持续到程序完成。在这种情况下确实如此,因为imain 中定义。

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


【解决方案1】:

将此程序编译成汇编时:

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

【讨论】:

  • 如果我在编译时初始化为i=7 或在运行时输入值,在这两种情况下,内存都会在运行时分配给 i。这是真的还是假的?
  • 你说的是真的
  • 为什么说第一种情况是static memory allocation 而第二种情况是dynamic memory allocation
  • 使用堆为i分配空间是动态的
  • 在您的评论中,It 指的是the second case(运行时输入)??我们如何使用堆为i 分配空间?
【解决方案2】:

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 循环并在循环退出时释放。在实践中(至少在我熟悉的平台上),两者的空间都将在函数入口处留出并在函数出口处释放,但你不应该假设y 的空间将在外部可用循环。

大多数系统使用堆栈来管理具有自动存储持续时间的对象1

具有动态 存储持续时间的对象通过调用库函数malloccallocrealloc 将其内存留出,并保留该内存直到它被显式释放致电free:

void *foo( void )
{
  void *mem = malloc( SOME_MEMORY );
  ...
  return mem;
}

void bar( void )
{
  void *data = foo();
  ...
  free( data );
}

变量membar 都具有自动存储持续时间。 mem 仅存在于foo 中,数据仅存在于bar 中。但是,它们都指向的对象具有动态存储持续时间;它在foo 中分配并保留到bar 中明确发布。

这些对象的内存池通常被称为“堆”。


1。 C 最初是在使用堆栈来管理运行时数据的系统上设计的,因此它是实现auto 变量行为的自然方式。但是,语言定义的编写方式是为了适应非基于堆栈的系统,尽管实现起来会很麻烦。

【讨论】:

  • 用过非栈系统,真是头疼。
  • This is usually done by reserving space within the program image itself. 请详细说明一下?
  • @kevingomes:生成的二进制文件中的某些部分将保留用于存储静态数据项;这些数据项将占用与程序文本(代码)相同的内存段,而不是堆栈或堆,它们是内存中的不同段。这样,一旦你的程序被加载到内存中(甚至在main 执行之前),这些数据项就会存在,并且会一直存在,直到程序被卸载。
【解决方案3】:

在 C 中有四种存储形式:

  • 自动(又名堆栈)
  • 线程
  • 静态
  • 已分配(又名堆)

一些作者将它们分为两类,静态和动态。每个人都同意 static 是静态的,而 allocated 是动态的,但是您的示例是 automatic,因此将其分配给其他类别之一是相当随意的。对我来说,只使用标准术语似乎更清楚。

【讨论】:

    【解决方案4】:

    编译代码时,编译器决定为每个对象(例如变量或函数代码)分配多少内存,它们将按什么顺序放置在内存中以及在什么地址。当然变量可能要等到程序启动后才会创建,但是内存是提前分配好的,变量地址已经编译到代码中了——比如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; 声明,无论是否被认为是动态的,肯定是不是 静态 分配(即使它是main(),其执行时间涵盖几乎整个过程的执行时间)。

    【讨论】:

    【解决方案5】:

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

    在执行过程中出现了静态和动态的概念。执行时静态内存分配在数据或代码段之一中。动态分配发生在您调用 malloc 或 calloc 在堆中获取内存时,这仅在包含 malloc 或 calloc 的语句发生并且它们被称为动态时发生。

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

    【讨论】:

      猜你喜欢
      • 2012-01-13
      • 2014-10-03
      • 2016-02-01
      • 2016-02-03
      • 2016-10-21
      • 2015-02-27
      • 2013-11-10
      • 2015-07-23
      相关资源
      最近更新 更多