静态内存分配和动态内存分配之间的区别

Nis*_*mar 80 c memory memory-management dynamic-memory-allocation static-memory-allocation

我想知道静态内存分配和动态内存分配有什么区别?

你能用任何一个例子解释一下吗?

bri*_*ice 106

这是一个标准的面试问题:

动态内存分配

是存储在系统运行时分配的calloc(),malloc()和朋友.它有时也被称为"堆"内存,尽管它与堆数据结构ref无关.

int * a = malloc(sizeof(int));
Run Code Online (Sandbox Code Playgroud)

堆内存是持久的,直到free()被调用.换句话说,您可以控制变量的生命周期.

自动内存分配

这就是通常所说的"堆栈"内存,并在您输入新范围时分配(通常在调用堆栈上推送新函数时).移出作用域后,自动内存地址的值未定义,访问它们错误的.

int a = 43;
Run Code Online (Sandbox Code Playgroud)

请注意,范围不一定意味着功能.范围可以嵌套在一个函数中,并且该变量仅在声明它的块内是范围内的.另请注意,未指定分配此内存的位置.(在一个理智的系统上,它将在堆栈上,或注册优化)

静态内存分配

在编译时分配,静态内存中变量的生命周期是程序生命周期.

在C中,可以使用static关键字分配静态内存.范围仅是编译单元.

考虑关键字时,extern事情变得更有趣.当一个extern是可变的定义编译器为它分配内存.当一个extern变量声明,编译器要求变量被定义在别处.未声明/定义extern变量将导致链接问题,而声明/定义static变量失败将导致编译问题.

在文件范围内,static关键字是可选的(在函数之外):

int a = 32;
Run Code Online (Sandbox Code Playgroud)

但不是在函数范围内(函数内部):

static int a = 32;
Run Code Online (Sandbox Code Playgroud)

从技术上讲,externstatic是C中两个独立的变量类.

extern int a; /* Declaration */
int a; /* Definition */
Run Code Online (Sandbox Code Playgroud)

注册记忆

最后一个内存类是'register'变量.正如所料,寄存器变量应该分配在CPU的寄存器中,但实际上决定是由编译器决定的.您不能使用address-of将寄存器变量转换为引用.

register int meaning = 42;
printf("%p\n",&meaning); /* this is wrong and will fail at compile time. */
Run Code Online (Sandbox Code Playgroud)

大多数现代编译器都比你选择哪些变量放在寄存器中更聪明:)

参考文献:

有关静态内存分配的说明

说编译时分配静态内存有点令人困惑,特别是如果我们开始考虑编译机器和主机可能不相同或者甚至不在同一架构上.

认为静态内存的分配由编译器处理而不是在编译时分配可能更好.例如,编译器可以data在编译的二进制文件中创建大的部分,并且当程序被加载到存储器中时,程序data段内的地址将被用作分配的存储器的位置.如果使用大量静态内存,则具有使编译的二进制文件非常大的明显缺点.可以编写一个从不到六行代码生成的数千兆字节二进制文件.另一种选择是编译器注入初始化代码,该代码将在程序执行之前以其他方式分配内存.此代码将根据目标平台和操作系统而有所不同.实际上,现代编译器使用启发式方法来决定使用哪些选项.您可以通过编写一个小型C程序来自己尝试,该程序分配10k,1m,10m,100m,1G或10G项目的大型静态数组.对于许多编译器,二进制大小将随着数组的大小而线性增长,并且经过某一点,当编译器使用另一个分配策略时,它将再次缩小.

  • 注意:我建议`int*a = malloc(sizeof(*a));`而不是重复`a`的类型.如果`a`的类型发生变化,这会使事情变得更容易. (3认同)
  • "静态内存分配......在编译时分配"你的意思是在编译时分配大小是_determined_吗?内存的预留只会在运行时发生吗? (2认同)

Con*_*ius 78

分配有三种类型 - 静态,自动和动态.

静态分配意味着在程序启动时分配变量的内存.创建程序时,大小是固定的.它适用于全局变量,文件范围变量以及使用已static定义的内部函数限定的变量.

为函数内部定义的(非静态)变量进行自动内存分配,并且通常存储在堆栈中(尽管C标准并未强制要求使用堆栈).您不必使用它们来保留额外的内存,但另一方面,也限制了对此内存的生命周期的控制.例如:函数中的自动变量仅在函数完成之前存在.

void func() {
    int i; /* `i` only exists during `func` */
}
Run Code Online (Sandbox Code Playgroud)

动态内存分配有点不同.您现在可以控制这些内存位置的确切大小和生命周期.如果你没有释放它,你将遇到内存泄漏,这可能会导致应用程序崩溃,因为在某些时候,系统无法分配更多的内存.

int* func() {
    int* mem = malloc(1024);
    return mem;
}

int* mem = func(); /* still accessible */
Run Code Online (Sandbox Code Playgroud)

在上面的示例中,即使函数终止,分配的内存仍然有效且可访问.完成内存后,你必须释放它:

free(mem);
Run Code Online (Sandbox Code Playgroud)

  • -1这个答案错了​​.您混淆[静态](http://en.wikipedia.org/wiki/Static_variable)和[自动](http://en.wikipedia.org/wiki/Automatic_variable)变量. (5认同)
  • 当然你可以控制变量的生命周期......你是决定范围的那个,对吧? (2认同)
  • 你自己的句子写道:"*静态*分配意味着,你的变量的内存是*自动*分配"这是**错**.看看[GNU的libc手册页](http://www.gnu.org/software/libc/manual/html_node/Memory-Allocation-and-C.html)对此有何看法. (2认同)