C/C++面试八股题(五)

更多专栏:

超详细的嵌入式面经专栏(适用于小白学习和大佬复习):https://www.nowcoder.com/creation/manager/columnDetail/mGYoDz

校招公司汇总专栏:https://www.nowcoder.com/creation/manager/columnDetail/0ybKdp

目录:

1.(内存)堆和栈的区别是什么?

2.什么是堆,栈,内存泄漏和内存溢出?

3.什么是内存池?

4.请你说说什么是内存碎片?

5.在函数中申请堆内存需要注意什么?

内容:

1.(内存)堆和栈的区别是什么?

栈简介:

  • 栈由操作系统自动分配释放 ,用于存放函数的参数值、局部变量等,其操作方式类似于数据结构中的栈。参考如下代码:
int main() {
    int b; //栈
    char s[] = "abc"; //栈
    char *p2; //栈
}


其中函数中定义的局部变量按照先后定义的顺序依次压入栈中,也就是说相邻变量的地址之间不会存在其它变量。栈的内存地址生长方向与堆相反,由高到底,所以后定义的变量地址低于先定义的变量,比如上面代码中变量 s 的地址小于变量 b 的地址,p2 地址小于 s 的地址。栈中存储的数据的生命周期随着函数的执行完成而结束。

堆简介:

  • 堆由开发人员分配和释放, 若开发人员不释放,程序结束时由 OS 回收,分配方式类似于链表。参考如下代码:
int main() {
    // C 中用 malloc() 函数申请
    char* p1 = (char *)malloc(10);
    cout<<(int*)p1<<endl;    //输出:00000000003BA0C0

    // 用 free() 函数释放
    free(p1);
   
    // C++ 中用 new 运算符申请
    char* p2 = new char[10];
    cout << (int*)p2 << endl;    //输出:00000000003BA0C0
  
    // 用 delete 运算符释放
    delete[] p2;
}


关于堆上内存空间的分配过程,首先应该知道操作系统有一个记录空闲内存地址的链表,当系统收到程序的申请时,会遍历该链表,寻找第一个空间大于所申请空间的堆节点,然后将该节点从空闲节点链表中删除,并将该节点的空间分配给程序。

内存分配方式:

  • 栈:栈是由操作系统自动管理的内存区域,按照“先进后出”的规则进行管理。当函数被调用时,它的局部变量和参数会被压入栈中,函数结束后,相关的内存空间会被自动释放。
  • :堆是由程序员手动管理的内存区域,内存分配和释放是通过mallocfree(C语言)或newdelete(C++语言)来控制的。堆内存没有自动回收机制,需要程序员显式释放,否则可能导致内存泄漏。

生命周期:

  • :生命周期较短。栈中的变量在函数调用时创建,函数返回时销毁。通常仅限于函数的执行期间。
  • :生命周期由程序员控制。堆中的对象可以在程序运行时动态创建,直到调用freedelete释放内存。

存储方式:

  • :栈内存是线性结构,存储的是局部变量和函数调用信息。每个线程都有自己的栈空间。
  • :堆内存是一个较大的自由区域,存储动态分配的对象和数组等。堆内存中的对象之间没有顺序,程序员负责管理。

分配速度:

  • :栈内存的分配和释放速度非常快,因为它是顺序操作(栈顶入栈或出栈),无需复杂的管理。
  • :堆内存的分配和释放速度较慢,因为堆内存管理需要处理碎片化、内存查找等问题。

内存大小:

  • :栈的内存空间较小,通常有限制。栈的大小由操作系统或编译器设置。栈空间的不足会导致“栈溢出”。
  • :堆的内存空间较大,通常只有物理内存的限制。堆空间的大小通常不受操作系统限制,但分配和管理的开销较大。

内存碎片化:

  • :栈操作遵循"先进后出"的原则,不会有内存块从栈中弹出,因此不会产生碎片。
  • :堆是通过动态分配内存的方式进行分配和释放,频繁的申请和释放内存可能会引发内存碎片问题。

总结:

  • :自动管理、快速分配、内存有限、生命周期短、容易栈溢出。
  • :手动管理、分配较慢、内存空间大、生命周期长、容易造成内存泄漏。

2.什么是堆,栈,内存泄漏和内存溢出?

内存泄漏:

内存泄漏是指程序在运行过程中,动态分配了内存(通常在堆上),由于缺乏正确的内存释放操作,导致这些内存空间无法被回收,造成内存的浪费。

原因:

  • 程序员忘记释放已经分配的内存。内存指针丢失,无法访问已分配的内存。内存引用计数错误(例如在某些语言中,程序员可能没有正确管理内存引用计数)。

后果

  • 内存泄漏会导致程序消耗越来越多的内存,直到系统内存耗尽,程序可能崩溃或者系统变慢。在长时间运行的程序(如服务器)中,内存泄漏特别严重,因为它会不断积累。

解决方法

  • 使用智能指针。在C/C++中使用free、delete等手动释放内存。

例子 :

#include <iostream>
using namespace std;

void memoryLeak() {
    int* ptr = new int[100];  // 动态分配内存
    // 忘记释放内存
}

int main() {
    while (true) {
        memoryLeak();  // 每次调用都会分配新的内存,但没有释放
    }
    return 0;
}

在上面的代码中,每次调用memoryLeak函数时,都会动态分配一个int类型的数组(100个整数)。然而,delete[] ptr; 语句没有被调用来释放内存,这会导致程序每次调用时都占用新的内存空间,导致内存泄漏。

解决方法:

#include <iostream>
using namespace std;

void memoryLeak() {
    int* ptr = new int[100];  // 动态分配内存
    // 执行一些操作...
    delete[] ptr;  // 释放内存
}

int main() {
    whi

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

嵌入式/C++八股 文章被收录于专栏

本人双飞本,校招上岸广和通。此专栏覆盖嵌入式常见面试题,有C/C++相关的知识,数据结构和算法也有嵌入式相关的知识,如操作系统、网络协议、硬件知识。本人也是校招过来的,大家底子甚至项目,可能都不错,但是在面试准备中常见八股可能准备不全。此专栏很适合新手学习基础也适合大佬备战复习,比较全面。最终希望各位友友们早日拿到心仪offer。也希望大家点点赞,收藏,送送小花。这是对我的肯定和鼓励。 持续更新

全部评论
友友们有什么建议可以指出哦
4 回复 分享
发布于 2024-12-11 16:55 陕西
博主有些说的还是不够简洁,像内存碎片那块我简单理解 内:当分配给进程的内存大于所需大小时,其中剩余空间成为内部碎片 外:未分配的连续内存空间太小分配不能满足时,导致内存无法有效利用就出现外部碎片
3 回复 分享
发布于 2024-12-11 20:07 陕西
博主快更快更
2 回复 分享
发布于 2024-12-13 17:06 陕西
堆栈这块不全诶 数据结构相关堆栈 没有解释
1 回复 分享
发布于 2024-12-13 22:46 陕西
期待继续更新
1 回复 分享
发布于 2024-12-14 11:49 江苏
有一个疑问,既然堆中程序员申请了内存没释放可以由系统释放,那咋还泄露呢
1 回复 分享
发布于 2024-12-14 12:24 江苏
欢迎大家订阅此专栏,订阅点赞收藏送花后,截图si聊我,免费赠送嵌入式学习资料大礼包(含简历模版、c/c++、嵌入式等资料)
1 回复 分享
发布于 2024-12-14 15:59 陕西
已订阅求嵌入式资料
1 回复 分享
发布于 2024-12-16 20:10 陕西

相关推荐

评论
23
32
分享

创作者周榜

更多
牛客网
牛客企业服务