MST

星途 面试题库

面试题:C语言中堆内存与栈内存分配的区别

请详细阐述C语言中堆内存分配(如使用malloc等函数)和栈内存分配(如局部变量的分配)在分配方式、生命周期、内存管理等方面的区别。
46.5万 热度难度
编程语言C

知识考点

AI 面试

面试题答案

一键面试

分配方式

  1. 堆内存分配
    • 使用函数如malloccallocrealloc等来手动分配内存。例如,int *ptr = (int *)malloc(sizeof(int));通过malloc函数向操作系统请求一块指定大小的内存空间,返回一个指向该内存起始地址的指针。分配的内存位置是由操作系统的堆管理器在堆空间中动态确定的,不一定是连续的内存块。
  2. 栈内存分配
    • 当函数被调用时,其局部变量在栈上自动分配内存。例如,在函数void func() { int num; }中,num变量在函数func被调用时,会在栈上自动分配一个int类型大小的内存空间。栈内存的分配是由编译器自动处理的,按照一定的规则(通常是后进先出),分配的内存是连续的,并且随着函数调用的结束自动释放。

生命周期

  1. 堆内存分配
    • 生命周期从调用内存分配函数(如malloc)成功开始,直到调用相应的释放函数(如free)为止。如果在程序中没有及时调用free释放堆内存,会导致内存泄漏。例如,下面的代码中如果没有free(ptr)ptr指向的堆内存一直不会被释放:
int *ptr = (int *)malloc(sizeof(int));
// 使用ptr
// 没有free(ptr)会导致内存泄漏
  1. 栈内存分配
    • 栈内存中局部变量的生命周期与函数的调用和返回紧密相关。当函数被调用时,局部变量在栈上分配内存,函数执行结束时,栈上为这些局部变量分配的内存自动被释放。例如:
void func() {
    int num = 10;
    // num在函数调用时分配内存
}
// 函数结束,num占用的栈内存自动释放

内存管理

  1. 堆内存分配
    • 开发者需要手动管理堆内存的释放。在使用完堆内存后,必须调用free函数释放已分配的内存,否则会造成内存泄漏。例如:
int *ptr = (int *)malloc(sizeof(int));
// 使用ptr
free(ptr);
  • 堆内存的分配和释放可能会导致内存碎片的产生。频繁的分配和释放不同大小的内存块,可能会使得堆中出现一些不连续的空闲内存块,这些小块内存无法满足后续较大内存分配请求,从而降低内存的使用效率。
  1. 栈内存分配
    • 编译器自动管理栈内存的分配和释放,开发者无需手动干预。当函数返回时,栈帧被销毁,栈上的局部变量内存自动释放。这使得栈内存管理相对简单,不容易出现内存泄漏问题。但栈的大小通常是有限的,如果局部变量过多或者递归调用过深,可能会导致栈溢出错误。例如:
void recursiveFunc() {
    int largeArray[1000000];
    recursiveFunc();
    // 可能导致栈溢出
}