1.2 C/C++ 内存
一、C++ 内存管理
程序的虚拟地址空间通常划分为:代码段、数据段、BSS 段、堆区、文件映射区、栈区。
(注意:段的划分由编译器决定,虚拟地址布局与物理内存分配由操作系统管理,这句话面试官是问过我的)
文件映射区:主要用于加载动态链接库,以及实现外存文件到虚拟地址空间的映射。
二、C 语言中,内存分配的方式有几种?
1、静态存储区分配:内存分配在编译前完成,且在程序的整个运行期间存在。
2、栈上分配:函数内的局部变量。
3、堆上分配。
三、堆与栈的区别?
1、申请方式上:栈自动分配,堆手动分配。
2、申请大小限制:栈由高地址向低地址开辟,并且连续,但是空间小;堆由低地址向高地址开辟,不连续,但是大。
3、申请效率:栈由系统自动分配,速度快;堆人为分配,速度慢。
4、生命周期:堆需要手动释放,并且不受函数调用关系限制;栈自动释放。
5、能否产生内存碎片:栈不会;堆可能会。
四、栈在 C 语言中有什么作用?
1、可以用来存储临时变量,如,局部变量,函数参数,函数返回值,函数中的临时变量,寄存器值,函数返回地址等。
2、栈是多线程编程的基石,每个线程都最少有一个专属的栈。
3、中断和异常处理也有专属的栈。
五、C 语言函数参数的压栈顺序
C 语言采用自右向左的方式对函数参数压栈,这样处理起来比较方便,如 printf。
六、C++ 中拷贝赋值构造函数可以按值传递吗?
不可以,如果按值传递,传入参数本身就是一个临时对象,那这样的话,需要先对函数参数对象进行拷贝复制构造函数,这样就会造成死循环。
七、内存泄露
申请了一段堆空间,但在使用结束后并没有对其释放。虽然在程序结束后,系统可以对其释放,但在程序运行期间,这部分内存空间无法被其他进程申请。(所以这就引出了智能指针,关于智能指针的考点在后续章节)
八、内存溢出
定义:程序在运行过程中尝试访问超过其分配内存空间范围的内存区域。
常见情况:1、栈溢出(函数调用中递归层级过深,或者局部变量所需空间太大,超出栈的范围)。
2、缓冲区溢出(当向一个固定大小的缓冲区写入超过其容量的数据时,会导致写到相邻内存区域,如strcpy)。
3、数据溢出(如使用malloc分配的空间小,但写入的数据超过所分配的内存空间)。
九、strcpy 与 memcpy 的区别?
strcpy 用于字符串拷贝,直到遇到 '\0' 停止,仅适用于字符串。memcpy 用于字节级别的拷贝,会直接从源地址复制指定个字节到目标地址。
strcpy(dest, src); memcpy(dest, src, n);
十、重写 memcpy 需要注意的问题
检查内存是否有重叠,如果有需要从后向前拷贝,避免覆盖。
入参检查:指针有效性、size 应为正数。
尽量按机器字长拷贝,减少内存访问次数。
十一、malloc、calloc区别?
malloc:只是分配内存块;calloc:不仅分配指定大小的内存块,还会将内存中的内容初始化为 0;
int* arr = (int*)calloc(5, sizeof(int)); // 分配并清零 int* arr = (int*)malloc(5 * sizeof(int)); memset(arr, 0, 5 * sizeof(int)); // 等效calloc的效果
十二、malloc 底层原理
1、当开辟的空间小于 128K 时,调用 brk() 函数,malloc 的底层实现是系统调用函数 brk(),其主要移动指针 _enddata (此时的 _enddata 指的是 Linux 地址空间中堆段的末尾地址,不是数据段的末尾地址)。
2、当开辟的空间大于 128K 时,mmap()系统调用函数来在虚拟地址空间中(堆和栈中间,称为“文件映射区域”的地方)找一块空间来开辟。
具体实现:
1、当调用 malloc(size) 时,它首先计算需要分配的内存块大小,包括用户请求的大小以及内存管理所需的额外空间(例如内存块的管理信息)。
2、malloc 会遍历一个数据结构(例如空闲链表或空闲块列表),查找合适大小的空闲内存块。
3、如果找到了合适的内存块,malloc 会将其标记为已分配,并返回一个指向该内存块的指针给用户。
4、如果没有足够大的空闲内存块可用,malloc 可能需要扩展程序的虚拟内存空间。它通过系统调用(例如 brk 或 mmap)向操作系统请求更多的连续内存空间。
5、当操作系统提供了更多的内存空间后,malloc 可以从新的空间中分配出合适大小的内存块,并将其标记为已分配。
6、在内存块被释放时,通过调用 free 函数,malloc 将其标记为未分配,并将该内存块添加到空闲内存块的列表中,以便后续的内存分配可以重复使用它们。
一名985硕,在25年秋招中斩获多个C++/嵌入式开发Offer。本专栏将分享我的面经,涵盖C/C++、操作系统、计算机网络、ARM体系与架构、Linux应用/驱动开发、Qt、通信协议及开发工具链等核心内容。
查看13道真题和解析