三、内存管理、指针与堆栈

三、内存管理、指针与堆栈(共16项)

1.C/C++中的new和malloc有什么区别?

2.C++中new、delete、malloc、free关系

3.C++中介绍一下delete与 delete\[\]区别

4.介绍一下newoperator和operatornew的区别

5.main函数执行之前会执行什么? 执行之后还能执行代码吗?

6.堆和栈的区别有什么?

7.程序的局部变量、全局变量、及动态申请的数据分别存储在哪里?

8.编程实现memcopy

9.C/C++中struct的内存对齐与内存占用计算?

10.C/C++中智能指针的定义与作用?

11.C/C++中内存泄漏以及解决方法?

12.空指针和悬空指针的区别?

13.什么是智能指针,它的作用有哪些,智能指针有什么缺点?

14.应用程序在运行时的内存包括代码区和数据区,其中数据区又包括哪些部分?

15.介绍一下c++内存泄漏?

16.C++智能指针在模型服务中如何选择?

结论先行

这16个问题覆盖了 C++ 内存生命周期三阶段:分配(new/malloc/operator new)→ 使用(栈/堆/数据区)→ 回收(delete/free/智能指针)

核心主线是:理解堆栈差异、掌握手动分配规则、用智能指针替代裸指针、避免内存泄漏与悬空指针 🔐


逐条简明解释

1. newmalloc 的区别
维度 new / delete malloc / free
语言 C++ 操作符 C 库函数
分配类型 按对象/数组分配,自动计算大小 按字节分配,需手动指定 sizeof
初始化 会调用构造函数 只分配内存,不构造
释放配套 delete / delete[] free
失败行为 抛出 std::bad_alloc 返回 NULL
可重载 可重载 operator new 不可重载
2. newdeletemallocfree 的关系
  • new = operator new(分配内存) + 调用构造函数
  • delete = 调用析构函数 + operator delete(释放内存)
  • malloc/free 只是纯内存分配/释放,不处理对象生命周期 ⚠️

不能混用new 出来的用 deletemalloc 出来的用 free

3. deletedelete[] 的区别
  • delete:释放单个对象,调用一次析构函数。

  • delete[]:释放对象数组,对每个元素调用析构函数,并读取数组长度信息。

    int* a = new int[10];
    delete[] a; // ✅ 正确
    // delete a; // ❌ 只析构第一个,未定义行为

4. new operatoroperator new 的区别
  • new operator :语法 new T,先分配内存再构造对象,不可重载。

  • operator new:底层内存分配函数,只负责"挖内存",可重载。

    void* p = operator new(sizeof(T)); // 只分配
    new (p) T(); // 在已有内存上构造(placement new)

5. main 函数执行前会执行什么?执行后还能执行代码吗?

执行前

  • 加载可执行文件,初始化全局/静态变量。
  • 调用全局对象的构造函数。
  • 初始化 C 运行时环境、命令行参数 argc/argv

执行后

  • main 返回后还可以执行代码,比如全局对象的析构函数、通过 atexit 注册的函数。
  • C++11 起可用 std::atexit 注册退出处理。
6. 堆和栈的区别
特性 栈(Stack) 堆(Heap)
分配速度 快(SP 移动即可) 慢(需查找合适内存块)
大小 有限(通常几 MB) 较大(受系统内存限制)
生命周期 随函数调用/返回自动管理 手动管理,需 delete/free
碎片 容易产生内存碎片
用途 局部变量、函数参数 动态分配的大对象、生命周期跨函数的对象
7. 局部变量、全局变量、动态申请数据存储在哪里?
变量类型 存储区域
局部变量 栈区
全局变量 / 静态变量 数据区(全局/静态存储区)
动态申请(new/malloc 堆区
常量字符串 / 字面量 常量区(代码区附近)
8. 编程实现 memcpy
复制代码
void* my_memcpy(void* dest, const void* src, size_t n) {
    char* d = static_cast<char*>(dest);
    const char* s = static_cast<const char*>(src);
    if (d == s) return dest;
    
    // 未处理内存重叠,若重叠请用 memmove
    while (n--) {
        *d++ = *s++;
    }
    return dest;
}

⚠️ 真实 memcpy 会按字长拷贝、处理对齐,且不处理内存重叠

9. struct 的内存对齐与占用计算

编译器按成员最大对齐数对齐,填充空白字节。

复制代码
struct S {
    char a;      // 1
    // 3 bytes padding
    int b;       // 4
    char c;      // 1
    // 3 bytes padding
};               // 总大小 12

规则:

  • 每个成员的偏移量是其对齐值的倍数。
  • 结构体总大小是最大对齐值的倍数。
  • 可用 #pragma pack(n)alignas 修改对齐。
10. 智能指针的定义与作用

C++11 起提供三种智能指针:

  • std::unique_ptr:独占所有权,不可复制,可移动。
  • std::shared_ptr:共享所有权,引用计数。
  • std::weak_ptr:弱引用,不增加引用计数,用于打破循环引用。

作用:自动管理内存生命周期,避免内存泄漏和悬空指针 🎯

11. 内存泄漏及解决方法

内存泄漏:动态分配的内存未被释放,程序长期运行后内存持续增长。

解决方法:

  1. 遵循"谁申请谁释放"原则。
  2. 使用 RAII 和智能指针。
  3. 避免异常路径下遗漏 delete
  4. 使用 Valgrind、AddressSanitizer 等工具检测。
12. 空指针和悬空指针的区别
类型 含义 示例
空指针 不指向任何有效对象的指针,值为 nullptr / NULL int* p = nullptr;
悬空指针 指向曾经有效、但已被释放或越界的内存 int* p = new int; delete p; // p 悬空

空指针可判断,悬空指针难以察觉,危害更大 💥

13. 智能指针的作用与缺点

作用

  • 自动释放资源。
  • 明确所有权语义。
  • 异常安全。

缺点

  • shared_ptr 有引用计数开销和循环引用风险。
  • 不能替代所有裸指针场景(如非所有权指针、C 接口)。
  • 误用(如用多个 shared_ptr 管理同一裸指针)会导致重复释放。
14. 程序运行时内存的数据区包括哪些部分?
复制代码
代码区
数据区
├── 已初始化全局/静态变量区(.data)
├── 未初始化全局/静态变量区(.bss)
├── 堆区(Heap)
└── 栈区(Stack)
常量区(.rodata,只读数据)
15. C++ 内存泄漏介绍

常见类型:

  • 未释放new 后没有 delete
  • 异常泄漏 :异常抛出时跳过 delete
  • 循环引用 :两个 shared_ptr 互相引用。
  • 资源泄漏:文件句柄、锁、网络连接未释放。

解决思路:RAII + 智能指针 + 工具检测

16. C++ 智能指针在模型服务中如何选择?
场景 推荐
模型实例、推理引擎等唯一所有者 std::unique_ptr
多个组件共享同一个模型/上下文 std::shared_ptr
缓存、回调、避免循环引用 std::weak_ptr
插件返回给框架的接口对象 std::shared_ptr<Base>std::unique_ptr<Base>
临时借用,不拥有所有权 裸指针或引用

模型服务中常用 shared_ptr 管理会话和模型句柄,unique_ptr 管理一次性资源,尽量避免裸指针持有所有权 🧠


整体联系

这16题串起了 C++ 内存管理的完整链条:

分配 new/malloc

使用 栈/堆/数据区

回收 delete/free

智能指针自动管理

避免泄漏/悬空指针

模型服务中的资源生命周期管理

理解这套机制,是写出高性能、稳定、可维护 C++ 服务(尤其是推理、模型部署类服务)的基础 🚀

相关推荐
笨笨饿2 小时前
#110_SCH3000 平台图传系统配置指南:从 DVP 摄像头到 UVC/WiFi 双通道传输
c语言·stm32·单片机·嵌入式硬件·物联网·vim
caimouse2 小时前
ReactOS 窗口系统分析(20):光标与图标 — cursoricon.c
c语言·开发语言
H_oRIZoN_2 小时前
Linux入门DAY23(C语言树形结构)
linux·c语言·数据结构
初夏睡觉2 小时前
原创题目 - 空壳恋爱
c++·算法·dp·oi·信息学·原创题目·值得挑战的题目
间歇性努力持续性发呆的野生快乐选手3 小时前
stl容器使用和算法简介
数据结构·c++
沙盘客4 小时前
AFSIM 官方案例库全景与解读方法论
c++·经验分享·后端
_wxd6665 小时前
STL-stack与queue与priority_queue(容器适配器)
c++
zh路西法5 小时前
【玩转VLA具身智能机械臂】(二):MoveIt2 运动规划——架构、配置与 C++ 上手
c++·机械臂·路径规划·vla·planner·moveit2
Yfhonier6 小时前
【素数定理】素数个数的位数
c++·算法·素数