三、内存管理、指针与堆栈共16项1.C/C中的new和malloc有什么区别2.C中new、delete、malloc、free关系3.C中介绍一下delete与 delete[]区别4.介绍一下newoperator和operatornew的区别5.main函数执行之前会执行什么 执行之后还能执行代码吗6.堆和栈的区别有什么7.程序的局部变量、全局变量、及动态申请的数据分别存储在哪里8.编程实现memcopy9.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.new和malloc的区别维度new/deletemalloc/free语言C 操作符C 库函数分配类型按对象/数组分配自动计算大小按字节分配需手动指定sizeof初始化会调用构造函数只分配内存不构造释放配套delete/delete[]free失败行为抛出std::bad_alloc返回NULL可重载可重载operator new不可重载2.new、delete、malloc、free的关系newoperator new分配内存 调用构造函数delete 调用析构函数 operator delete释放内存malloc/free只是纯内存分配/释放不处理对象生命周期 ⚠️不能混用new出来的用deletemalloc出来的用free。3.delete与delete[]的区别delete释放单个对象调用一次析构函数。delete[]释放对象数组对每个元素调用析构函数并读取数组长度信息。int* a new int[10]; delete[] a; // ✅ 正确 // delete a; // ❌ 只析构第一个未定义行为4.new operator与operator new的区别new operator语法new T先分配内存再构造对象不可重载。operator new底层内存分配函数只负责“挖内存”可重载。void* p operator new(sizeof(T)); // 只分配 new (p) T(); // 在已有内存上构造placement new5.main函数执行前会执行什么执行后还能执行代码吗执行前加载可执行文件初始化全局/静态变量。调用全局对象的构造函数。初始化 C 运行时环境、命令行参数argc/argv。执行后main返回后还可以执行代码比如全局对象的析构函数、通过atexit注册的函数。C11 起可用std::atexit注册退出处理。6. 堆和栈的区别特性栈Stack堆Heap分配速度快SP 移动即可慢需查找合适内存块大小有限通常几 MB较大受系统内存限制生命周期随函数调用/返回自动管理手动管理需delete/free碎片无容易产生内存碎片用途局部变量、函数参数动态分配的大对象、生命周期跨函数的对象7. 局部变量、全局变量、动态申请数据存储在哪里变量类型存储区域局部变量栈区全局变量 / 静态变量数据区全局/静态存储区动态申请new/malloc堆区常量字符串 / 字面量常量区代码区附近8. 编程实现memcpyvoid* my_memcpy(void* dest, const void* src, size_t n) { char* d static_castchar*(dest); const char* s static_castconst 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. 智能指针的定义与作用C11 起提供三种智能指针std::unique_ptr独占所有权不可复制可移动。std::shared_ptr共享所有权引用计数。std::weak_ptr弱引用不增加引用计数用于打破循环引用。作用自动管理内存生命周期避免内存泄漏和悬空指针11. 内存泄漏及解决方法内存泄漏动态分配的内存未被释放程序长期运行后内存持续增长。解决方法遵循“谁申请谁释放”原则。使用RAII和智能指针。避免异常路径下遗漏delete。使用 Valgrind、AddressSanitizer 等工具检测。12. 空指针和悬空指针的区别类型含义示例空指针不指向任何有效对象的指针值为nullptr/NULLint* 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_ptrBase或std::unique_ptrBase临时借用不拥有所有权裸指针或引用模型服务中常用shared_ptr管理会话和模型句柄unique_ptr管理一次性资源尽量避免裸指针持有所有权 整体联系这16题串起了 C 内存管理的完整链条分配 new/malloc使用 栈/堆/数据区回收 delete/free智能指针自动管理避免泄漏/悬空指针模型服务中的资源生命周期管理理解这套机制是写出高性能、稳定、可维护 C 服务尤其是推理、模型部署类服务的基础