资讯详情

【C/C++】 内存管理

📅 2026/9/28 8:23:18 | 华诺云谱 👁 阅读
【C/C++】 内存管理
目录1. C/C 的内存分布2. 回顾C语言动态内存管理方式3. C 动态内存管理方式3.1 new / delete 操作内置类型3.2 new / delete 操作自定义类型​编辑3.3 operator new 与 operator delete 函数重点4. new 和 delete 的实现原理4.1 内置类型4.2 自定义类型5. 总结 malloc / free 与 new / delete 的区别1. C/C 的内存分布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(sizeof(int) * 4); int* ptr2 (int*)calloc(4, sizeof(int)); int* ptr3 (int*)realloc(ptr2, sizeof(int) * 4); free(ptr1); free(ptr3); } 1. 选择题 选项: A.栈 B.堆 C.数据段(静态区) D.代码段(常量区) globalVar在哪里____ staticGlobalVar在哪里____ staticVar在哪里____ localVar在哪里____ num1 在哪里____ char2在哪里____ *char2在哪里___ pChar3在哪里____ *pChar3在哪里____ ptr1在哪里____ *ptr1在哪里____ int globalVar 1; static int staticGlobalVar 1; //glibalVar 是在main 外的全局域staticGlobalVar 本身已经是static 的静态变量了 //所以俩个都在数据段静态区 void Test() { static int staticVar 1; int localVar 1; int num1[10] { 1, 2, 3, 4 }; char char2[] abcd; const char* pChar3 abcd; //staticVar 本身是static 所以也是在静态区 //localVar 在栈区 // num1 和 *num1 都在栈区 // 同理 char2 和 *char2 也都在栈区 // pChar3 在战区 *pChar3并且无法更改变量在代码段常量区 int* ptr1 (int*)malloc(sizeof(int) * 4); int* ptr2 (int*)calloc(4, sizeof(int)); int* ptr3 (int*)realloc(ptr2, sizeof(int) * 4); free(ptr1); free(ptr3); // ptr1 ptr2 ptr3 都在栈区 // *ptr1 *ptr2*ptr3都在堆区 // 无需ptr2 进行空间释放 }1.栈区又叫堆栈——非静态局部变量/函数参数/放回值等等栈式向下增长的。2.内存映射段是高效的 I/O 映射方式用于装载一个共享的动态内存库。用户可使用系统接口 创建共享共享内存做进程间通信。Linux课程如果没学到这块现在只需要了解一下3.堆用于程序运行时动态内存分配堆是可以上增长的。4.数据段--存储全局数据和静态数据。5.代码段--可执行的代码/只读常量。2. 回顾C语言动态内存管理方式malloc calloc realloc free 代码展示void test() { int* p2 (int*)malloc(sizeof(int)*1); int* p3 (int*)realloc(p2,sizeof(int)*2); free(p3); }3. C 动态内存管理方式在C中与 malloc 和 free 类似申请空间和释放空间就是 new 和 delete 通过这两个操符进行动态空间管理。3.1 new / delete 操作内置类型#include iostream using namespace std; int main() { // 动态申请空间1个 int 类型的空间 int* arr new int; // 释放空间 arr delete arr; // 动态申请空间10个 int 类型的空间 arr new int[10]; delete[] arr; // 动态申请空间1个 int 类型的空间,并且初始化为10; arr new int(10); cout *arr endl; delete arr; return 0; }3.2 new / delete 操作自定义类型#include iostream #include stdlib.h using namespace std; class A { public: A(int a0) :_a(a) { cout A:a this endl; } ~A() { cout ~A:a this endl; } private: int _a 0; }; int main() { A* arr (A*)malloc(sizeof(A)); cout arr endl; A* arr1 new A(10); cout arr1 endl; free(arr); delete(arr1); return 0; }malloc 和 free 的空间申请和空间释放都没有去使用构造函数和析构只用new 和delelet 回去使用构造与析构函数。3.3 operator new 与 operator delete 函数重点在C 中new和delete是用户进行动态申请释放空间是操作符而new和delete又是由operator new和operator delete系统提供的全局函数new和delete底层分别都调用这两个函数operator new和operator delete一个通过申请空间和释放空间另一个通过释放空间。/* operator new该函数实际通过malloc来申请空间当malloc申请空间成功时直接返回申请空间 失败尝试执行空 间不足应对措施如果改应对措施用户设置了则继续申请否 则抛异常。 */ void *__CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc) { // try to allocate size bytes void *p; while ((p malloc(size)) 0) if (_callnewh(size) 0) { // report no memory // 如果申请内存失败了这里会抛出bad_alloc 类型异常 static const std::bad_alloc nomem; _RAISE(nomem); } return (p); } /* operator delete: 该函数最终是通过free来释放空间的 */ void operator delete(void *pUserData) { _CrtMemBlockHeader * pHead; RTCCALLBACK(_RTC_Free_hook, (pUserData, 0)); if (pUserData NULL) return; _mlock(_HEAP_LOCK); /* block other threads */ __TRY /* get a pointer to memory block header */ pHead pHdr(pUserData); /* verify block type */ _ASSERTE(_BLOCK_TYPE_IS_VALID(pHead-nBlockUse)); _free_dbg( pUserData, pHead-nBlockUse ); __FINALLY _munlock(_HEAP_LOCK); /* release other threads */ __END_TRY_FINALLY return; } /* free的实现 */ #define free(p) _free_dbg(p, _NORMAL_BLOCK)通过上面两个全局函数的实现直到operator new实际也是通过mallco的申请空间如果mallco申请空间可能出现空指针情况还需要进行判断而operator new不需要进行空指针中判断但是operator new会经行抛异常的我们需要进行捕获异常补充operator new优先申请空间在调用构造函数。operator delete也是通过free进行释放空间是先调用析构函数最后释放空间如果优先调用free会导致指针丢失位置导致野指针访问等等问题。通过反汇编来观察底层编译的进行情况4. new 和 delete 的实现原理4.1 内置类型内置类型的意思就是int这些编译器已有的类型内置类型的情况下mallco和new与delete和free两对的功能没有区别只有mallco需要进行判断是否申请空间是否成功而new需要抛异常。而delete[]和new A[N]都是连续释放空间和连续申请空间。4.2 自定义类型new 的原理优先调用 operator new 进行申请空间。再调用构造函数。delete 的原理优先调用析构函数。再调用 operator delete 进行空间释放。new A[N] 的原理优先调用 operator new[] ,再 operator new[] 内调用N次operator new 函数。再调用N次构造函数。delete[] 的原理优先调用N次析构函数。再调用 operator delete[],再operator delete[] 内调用N次 operator delete 函数进行空间释放。补充知识:在有析构函数的A类中使用new [] 的连续申请空间在arr1 之前的位置出现了一个特殊的4字节空间并且在这个4字节空间内存储了0a10大小VS 编译器默认小端模式与我们申请需要10个A类类型一致。在没有了析构函数这个4字节空间位置没有了。为什么有这个空间这个4字节空间是为delete[] 使用的在使用N次调用析构函数使用如果没有析构函数编译器默认生成的析构函数也用不着所以没有用户编译的析构函数就不需要这4个字节的空间。为什么是4个字节不是更大的因为就算4个字节全部占完申请一个(2^32-1)*n的内存大小内存已经报错了不需要这么多的更大的内存4个字节刚刚好这个4字节空间也只是作为标记的功能。5. 总结 malloc / free 与 new / delete 的区别malloc/free和new/delete的共同点是都是从堆上申请空间并且需要用户手动释放。不同的地方是1. malloc和free是函数new和delete是操作符2. malloc申请的空间不会初始化new可以初始化3. malloc申请空间时需要手动计算空间大小并传递new只需在其后跟上空间的类型即可如果是多个对象[]中指定对象个数即可4. malloc的返回值为void*,在使用时必须强转new不需要因为new后跟的是空间的类型5. malloc申请空间失败时返回的是NULL因此使用时必须判空new不需要但是new需要捕获异常6.申请自定义类型对象时malloc/free只会开辟空间不会调用构造函数与析构函数而new在申请空间后会调用构造函数完成对象的初始化delete在释放空间前会调用析构函数完成空间中资源的清理释放
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑