9、C/C++ 内存管理详解:从基础到面试题

📘 C/C++ 内存管理详解:从基础到面试题

本文系统梳理了 C/C++ 中的内存分布、动态内存管理方式、new/delete 的底层原理,以及常见面试题,适合初学者和求职者参考。


🎯 本文目标

  • 理解 C/C++ 程序的内存分布结构
  • 掌握 C 语言中的动态内存管理函数:malloc / calloc / realloc / free
  • 掌握 C++ 中的 new / delete 操作符及其底层机制
  • 理解定位 new 表达式(placement-new)
  • 掌握常见面试题与内存泄漏检测方法

🧠 1. C/C++ 程序内存分布

C/C++ 程序运行时的内存通常分为以下几个区域:

区域 内容说明
栈(Stack) 局部变量、函数参数、返回地址等,向下增长
堆(Heap) 动态分配的内存,向上增长
数据段 全局变量、静态变量
代码段 可执行代码和只读常量
内存映射段 文件映射、动态库、共享内存等

📌 示例变量归属

cpp 复制代码
int globalvar = 1;               // 数据段
static int staticGlobalvar = 1; // 数据段
void Test() {
    static int staticVar = 1;   // 数据段
    int localvar = 1;           // 栈
    int num1[10] = {1,2,3,4};   // 栈
    char char2[] = "abcd";      // 栈(字符数组)
    const char* pchar3 = "abcd";// 栈(指针)+ 代码段(字符串常量)
    int* ptr1 = (int*)malloc(4 * sizeof(int)); // 栈(指针)+ 堆(数据)
}

🧮 2. C语言动态内存管理函数

✅ 函数说明

函数 功能
malloc 分配指定大小的内存,内容未初始化
calloc 分配并初始化为 0
realloc 重新分配内存大小
free 释放已分配的内存

📌 示例代码

cpp 复制代码
int* p1 = (int*)malloc(sizeof(int));
free(p1);

int* p2 = (int*)calloc(4, sizeof(int));
int* p3 = (int*)realloc(p2, sizeof(int) * 10);
free(p3); // 不需要再 free(p2)

🚀 3. C++ 的动态内存管理方式

C++ 提供了更高级的 new / delete 操作符,支持对象构造与析构。

✅ 基本用法

cpp 复制代码
int* ptr1 = new int;        // 分配一个 int
int* ptr2 = new int(10);    // 分配并初始化
int* ptr3 = new int[3];     // 分配数组

delete ptr1;
delete ptr2;
delete[] ptr3;

✅ 自定义类型支持构造/析构

cpp 复制代码
class A {
public:
    A(int a = 0) : _a(a) { cout << "构造:" << this << endl; }
    ~A() { cout << "析构:" << this << endl; }
private:
    int _a;
};

A* p1 = new A(1);
delete p1;

🔍 4. operator new 与 operator delete 原理

✅ operator new

底层通过 malloc 分配空间,失败时尝试调用 _callnewh(),最终可能抛出 bad_alloc 异常。

✅ operator delete

底层通过 free 释放空间,并进行内存块验证与线程锁保护。


⚙️ 5. new/delete 的实现原理

内置类型

  • newmalloc 类似,但 new 会抛异常,malloc 返回 NULL
  • deletefree 类似

自定义类型

  • new:调用 operator new → 构造函数
  • delete:析构函数 → 调用 operator delete
  • new[] / delete[]:分别调用构造/析构函数 N 次

📦 6. 定位 new 表达式(placement-new)

用于在已分配的内存上构造对象,常用于内存池。

cpp 复制代码
void* raw = malloc(sizeof(A));
A* obj = new(raw) A(10); // 构造对象
obj->~A();               // 手动析构
free(raw);

🎯 7. 常见面试题汇总

✅ malloc/free vs new/delete

对比项 malloc/free new/delete
类型 函数 操作符
初始化 不初始化 可初始化
类型安全 需强转 类型明确
错误处理 返回 NULL 抛异常
构造/析构 不调用 自动调用

🧨 内存泄漏详解

什么是内存泄漏?

程序未释放已分配但不再使用的内存,导致资源浪费。

危害

  • 程序响应变慢
  • 系统资源耗尽
  • 程序崩溃或卡死

示例

cpp 复制代码
int* p = new int[10];
// 忘记 delete[] p; 就会造成泄漏

🛠️ 如何检测与避免内存泄漏

检测方法

  • Windows:使用 _CrtDumpMemoryLeaks()
  • Linux:使用 Valgrind 等工具

避免方法

  • 良好编码规范
  • 使用智能指针(RAII)
  • 使用公司内部内存管理库
  • 使用专业检测工具

✅ 总结

C/C++ 的内存管理是系统编程的核心技能,理解内存分布、掌握动态分配与释放机制、熟悉构造与析构行为,是写出高质量代码的基础。面试中常考这些知识点,建议配合代码练习与工具使用深入掌握。

相关推荐
爱编码的小八嘎4 分钟前
C语言对话-21.模板特化,缺省参数和其他一些有趣的事情
c语言
kokunka20 分钟前
【源码+注释】纯C++小游戏开发之射击小球游戏
开发语言·c++·游戏
C雨后彩虹23 分钟前
CAS与其他并发方案的对比及面试常见问题
java·面试·cas·同步·异步·
java1234_小锋1 小时前
Java高频面试题:SpringBoot为什么要禁止循环依赖?
java·开发语言·面试
2501_944525542 小时前
Flutter for OpenHarmony 个人理财管理App实战 - 账户详情页面
android·java·开发语言·前端·javascript·flutter
计算机学姐2 小时前
基于SpringBoot的电影点评交流平台【协同过滤推荐算法+数据可视化统计】
java·vue.js·spring boot·spring·信息可视化·echarts·推荐算法
yueyuexiaokeai12 小时前
linux kernel常用函数整理
linux·c语言
Filotimo_2 小时前
Tomcat的概念
java·tomcat
John_ToDebug2 小时前
浏览器内核崩溃深度分析:从 MiniDump 堆栈到 BindOnce UAF 机制(未完待续...)
c++·chrome·windows