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; }
关于堆上内存空间的分配过程,首先应该知道操作系统有一个记录空闲内存地址的链表,当系统收到程序的申请时,会遍历该链表,寻找第一个空间大于所申请空间的堆节点,然后将该节点从空闲节点链表中删除,并将该节点的空间分配给程序。
内存分配方式:
- 栈:栈是由操作系统自动管理的内存区域,按照“先进后出”的规则进行管理。当函数被调用时,它的局部变量和参数会被压入栈中,函数结束后,相关的内存空间会被自动释放。
- 堆:堆是由程序员手动管理的内存区域,内存分配和释放是通过
malloc
、free
(C语言)或new
、delete
(C++语言)来控制的。堆内存没有自动回收机制,需要程序员显式释放,否则可能导致内存泄漏。
生命周期:
- 栈:生命周期较短。栈中的变量在函数调用时创建,函数返回时销毁。通常仅限于函数的执行期间。
- 堆:生命周期由程序员控制。堆中的对象可以在程序运行时动态创建,直到调用
free
或delete
释放内存。
存储方式:
- 栈:栈内存是线性结构,存储的是局部变量和函数调用信息。每个线程都有自己的栈空间。
- 堆:堆内存是一个较大的自由区域,存储动态分配的对象和数组等。堆内存中的对象之间没有顺序,程序员负责管理。
分配速度:
- 栈:栈内存的分配和释放速度非常快,因为它是顺序操作(栈顶入栈或出栈),无需复杂的管理。
- 堆:堆内存的分配和释放速度较慢,因为堆内存管理需要处理碎片化、内存查找等问题。
内存大小:
- 栈:栈的内存空间较小,通常有限制。栈的大小由操作系统或编译器设置。栈空间的不足会导致“栈溢出”。
- 堆:堆的内存空间较大,通常只有物理内存的限制。堆空间的大小通常不受操作系统限制,但分配和管理的开销较大。
内存碎片化:
- 栈:栈操作遵循"先进后出"的原则,不会有内存块从栈中弹出,因此不会产生碎片。
- 堆:堆是通过动态分配内存的方式进行分配和释放,频繁的申请和释放内存可能会引发内存碎片问题。
总结:
- 栈:自动管理、快速分配、内存有限、生命周期短、容易栈溢出。
- 堆:手动管理、分配较慢、内存空间大、生命周期长、容易造成内存泄漏。
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++相关的知识,数据结构和算法也有嵌入式相关的知识,如操作系统、网络协议、硬件知识。本人也是校招过来的,大家底子甚至项目,可能都不错,但是在面试准备中常见八股可能准备不全。此专栏很适合新手学习基础也适合大佬备战复习,比较全面。最终希望各位友友们早日拿到心仪offer。也希望大家点点赞,收藏,送送小花。这是对我的肯定和鼓励。 持续更新