当前位置: 首页 > news >正文

河北网站建设备案长春互联网

河北网站建设备案,长春互联网,深圳市住房和建设局,南阳网站优化费用文章目录 前言一、内存分区1. 内存划分情况2. 最大内存计算 二、malloc/calloc/realloc 与 free1. malloc2. calloc3. realloc4. free5. 差异对比6. 失败处理 三、内存分配题目1. 题目2. 内存区域划分 四、C内存管理方式1. new 与 delete2. new/delete操作内置类型3. new和dele… 文章目录 前言一、内存分区1. 内存划分情况2. 最大内存计算 二、malloc/calloc/realloc 与 free1. malloc2. calloc3. realloc4. free5. 差异对比6. 失败处理 三、内存分配题目1. 题目2. 内存区域划分 四、C内存管理方式1. new 与 delete2. new/delete操作内置类型3. new和delete操作自定义类型 五、operator new与operator delete函数1. 原理2. 异常捕获方法 六、new和delete的实现原理1. 内置类型2. 自定义类型 七 、定位new表达式(placement-new)八、对比malloc/free和new/delete的区别总结 前言 今天我们来看C/C中对于内存的管理 一、内存分区 1. 内存划分情况 在C/C中数据的存储位置取决于数据类型和作用域。通常分为以下几类 栈Stack 自动变量局部变量、函数参数等会存储在栈上。当函数调用时栈帧分配用于存储这些变量函数结束后栈帧被销毁变量随之消失。特点栈内存分配快自动管理但空间有限通常为几MB。 堆Heap 动态分配的内存使用malloc、callocC语言或newC分配的内存位于堆上。程序员需手动管理堆内存使用freeC语言或deleteC释放。 特点堆空间大但分配速度较慢且需要手动释放易出现内存泄漏。 全局/静态区Global/Static 全局变量定义在函数外部的变量作用域为整个程序存储在全局/静态区。静态变量使用static修饰的变量即使定义在函数内生命周期也是整个程序运行期间存储在全局/静态区。特点内存一直保留直到程序结束。 常量区Text Segment/ROData 字符串字面值如Hello, World!这样的字符串存储在常量区只读不可修改。const修饰的变量也可以存储在常量区具体取决于编译器实现。 代码区Code Segment 函数代码编译后的程序代码如函数体存储在代码区程序执行时从这里读取指令。 2. 最大内存计算 在32位x86和64位x64架构中CPU的寻址能力决定了能够访问的最大内存空间。 32位x86架构 寻址能力在32位系统中CPU使用32位地址即4字节来表示内存地址。最大寻址空间32位地址可以表示的最大数值为 ( 2^{32} ) 即 4,294,967,296 个地址字节也就是4GB内存空间。具体解释CPU可以通过一个32位地址生成从0到(2^{32}-1)的地址这意味着它能够访问最多4GB的内存。 64位x64架构 寻址能力在64位系统中CPU使用64位地址即8字节来表示内存地址。理论最大寻址空间64位地址理论上可以表示的最大数值为 ( 2^{64} )即 18,446,744,073,709,551,616 个地址字节也就是 16 exabytesEB 的内存空间。实际情况目前的操作系统和硬件并不会使用所有的64位地址位。现代操作系统和硬件会限制实际的可用内存寻址范围。例如Windows 64位系统支持的最大内存一般为几TB到几十TB具体取决于版本和硬件的限制。 二、malloc/calloc/realloc 与 free 在C语言中malloc、calloc、realloc 和 free 是动态内存管理的四个重要函数。它们在程序运行时负责分配、重新分配和释放内存。下面详细讲解它们的工作机制并总结它们的区别。 1. malloc malloc (Memory Allocation) 功能分配指定大小的内存块。语法void* malloc(size_t size);其中size 是要分配的内存大小以字节为单位返回值是指向已分配内存块的指针。如果分配失败malloc 返回 NULL。特点 malloc 分配的内存块中的数据不初始化内容可能是随机的内存中的残留数据。适用于一次性分配特定大小的内存。 示例int* ptr (int*) malloc(10 * sizeof(int)); // 分配存储10个整数的内存2. calloc calloc (Contiguous Allocation) 功能分配内存并初始化为零。语法void* calloc(size_t num, size_t size);其中num 是要分配的元素个数size 是每个元素的大小以字节为单位。返回指向内存块的指针如果失败返回 NULL。特点 calloc 分配的内存会自动初始化为全零。适用于需要多个连续内存块的情况且希望这些内存块初始化为零。 示例int* ptr (int*) calloc(10, sizeof(int)); // 分配并初始化存储10个整数的内存calloc 就相当于 malloc memset 3. realloc realloc (Reallocation) 功能重新分配已分配内存的大小。语法void* realloc(void* ptr, size_t new_size);其中ptr 是指向之前分配的内存块的指针new_size 是新内存块的大小以字节为单位。realloc 返回指向新内存块的指针。特点 用于扩展或缩小已经分配的内存块。如果需要扩展且原有内存块之后的空间不够realloc 会在新位置分配内存并复制旧数据然后释放原有内存块如果足够则会在原位置上扩展。如果缩小内存块多余的内存将被释放但原始数据仍保留。 示例int* ptr (int*) realloc(ptr, 20 * sizeof(int)); // 将原来10个整数的内存扩展到20个realloc扩容空间的做法 4. free free (Memory Deallocation) 功能释放之前用 malloc、calloc 或 realloc 分配的内存。语法void free(void* ptr);其中ptr 是指向需要释放的内存块的指针。特点 必须为动态分配的内存显式调用 free否则会导致内存泄漏内存不会被释放导致系统内存资源逐渐减少。释放后指针指向的内存不再有效访问它会导致未定义行为例如访问已释放的内存可能引发段错误。 示例free(ptr); // 释放之前分配的内存5. 差异对比 总结malloc、calloc、realloc 与 free 的区别 函数名主要功能内存初始化参数用途malloc分配指定大小的内存块无内容未初始化size分配的字节数动态分配内存calloc分配并初始化内存全部初始化为0num元素个数size每个元素的大小分配多个内存块并初始化为零realloc重新分配已分配的内存原数据保留ptr原内存指针new_size新大小扩展或缩小现有内存free释放已分配的内存无释放操作ptr待释放的内存指针释放不再需要的内存 区别和应用场景 内存初始化malloc 分配的内存不初始化calloc 分配的内存会被初始化为 0。用法不同 使用 malloc 适合一次性分配已知大小的内存。使用 calloc 适合分配多个元素的内存块并且需要初始化为零。使用 realloc 适合在内存不足或需要调整内存时动态调整内存大小。 释放内存所有通过 malloc、calloc、realloc 分配的内存最后都必须通过 free 释放否则会造成内存泄漏。 6. 失败处理 对于如果开空间失败了怎么办 //realloc, calloc同理 int* ptr (int*) malloc(10 * sizeof(int)); if (ptr NULL) {// 内存分配失败的处理逻辑perror(malloc fail!);exit(-1); } 三、内存分配题目 1. 题目 我们先来看下面的一段代码和相关问题 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;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);} 选择题 选项: A.栈 B.堆 C.数据段(静态区) D.代码段(常量区) globalVar在哪里C staticGlobalVar在哪里C staticVar在哪里C localVar在哪里A num1 在哪里A 分析: globalVar全局变量在数据段 staticGlobalVar静态全局变量在静态区 staticVar静态局部变量在静态区 localVar局部变量在栈区 num1局部变量在栈区 char2在哪里A *char2在哪里A pChar3在哪里A *pChar3在哪里D ptr1在哪里A *ptr1在哪里B 分析: char2局部变量在栈区 char2是一个数组把后面常量串拷贝过来到数组中数组在栈上所以*char2在栈上 pChar3局部变量在栈区 *pChar3得到的是字符串常量字符在代码段 ptr1局部变量在栈区 *ptr1得到的是动态申请空间的数据在堆区 填空题 sizeof(num1) 40;//数组大小,10个整形数据一共40字节 sizeof(char2) 5;//包括\0的空间 strlen(char2) 4;//不包括\0的长度 sizeof(pChar3) 4;//pChar3为指针 strlen(pChar3) 4;//字符串“abcd”的长度不包括\0的长度 sizeof(ptr1) 4;//ptr1是指针 2. 内存区域划分 栈 又称堆栈用于存储非静态局部变量、函数参数、返回值等栈是向下增长的。 内存映射段 高效的I/O映射方式用于加载共享的动态内存库。通过系统接口创建共享内存进行进程间通信。如果还没学到这部分内容现在只需了解即可。 堆 用于程序运行时的动态内存分配堆是向上增长的。 数据段 存储全局变量和静态变量。 代码段 包含可执行代码和只读常量。 四、C内存管理方式 1. new 与 delete C语言内存管理方式在C中可以继续使用但有些地方就无能为力而且使用起来比较麻烦(主要是在对类)因此C又提出了自己的内存管理方式通过new和delete操作符进行动态内存管理。 2. new/delete操作内置类型 这段代码展示了在C中如何使用new和delete进行动态内存分配和释放。下面逐行讲解代码的含义 int main() {// 动态申请一个int类型的空间int* ptr4 new int;动态申请单个int类型的内存 使用new int分配一个int类型的内存空间并返回其地址赋值给指针ptr4。此时内存中的值未初始化可能是一个随机值。 // 动态申请一个int类型的空间并初始化为10int* ptr5 new int(10);动态申请单个int类型的内存并初始化 使用new int(10)分配内存并将其初始化为10。指针ptr5指向这个内存位置。 // 动态申请10个int类型的空间int* ptr6 new int[3];动态申请数组 使用new int[3]分配一个能够存储3个int的数组。内存中的值未初始化因此每个元素的值都是随机的。 int* ptr7 new int[3]{ 1,2,3 };动态申请数组并初始化 使用new int[3]{ 1,2,3 }分配一个能够存储3个int的数组并将第一个元素初始化为1第二个元素初始化为2第三个元素初始化为3。未指定的元素会被初始化为0。 int* ptr8 new int[5]{ 1,2,3 };动态申请更大数组并部分初始化 使用new int[5]{ 1,2,3 }分配一个能够存储5个int的数组前3个元素分别被初始化为1、2、3后2个元素自动初始化为0。 delete ptr4;delete ptr5;释放单个变量的内存 使用delete释放由new分配的单个int类型的内存。ptr4和ptr5所指向的内存空间被释放。 delete[] ptr6;delete[] ptr7;delete[] ptr8;释放数组的内存 使用delete[]释放动态分配的数组内存。ptr6、ptr7和ptr8分别指向的数组内存被正确释放。注意内存泄漏 使用 delete 释放一个数组分配的内存可能会导致内存泄漏(如释放这个数组不加[]),delete ptr6;。delete 只会释放第一个元素的内存后续元素的内存没有被正确释放这会使得程序中的内存使用逐渐增加。 3. new和delete操作自定义类型 现在我们有一个A类 class A { public:A(int a 1): _a(a){cout A(): this endl;}~A(){cout ~A(): this endl;} private:int _a; };int main() {// new/delete 和 malloc/free最大区别是 new/delete对于【自定义类型】除了开空间// 还会调用构造函数和析构函数A* p1 (A*)malloc(sizeof(A)); // 使用malloc申请内存A* p2 new A(1); // 使用new申请内存并调用构造函数内存分配 malloc分配内存给一个 A 类型的对象p1但不会调用构造函数。new A(1)分配内存并调用构造函数初始化 _a 为 1并将指针赋值给 p2。 free(p1); // 使用free释放内存delete p2; // 使用delete释放内存内存释放 free(p1)释放通过 malloc 分配的内存不会调用析构函数。delete p2释放通过 new 分配的内存同时会调用析构函数打印析构信息。 // 内置类型是几乎是一样的int* p3 (int*)malloc(sizeof(int)); // Cint* p4 new int; // Cfree(p3); // 释放p3delete p4; // 释放p4内置类型的内存管理 malloc 和 free 的使用与 new 和 delete 处理内置类型如 int几乎一样。malloc 不会初始化内存而 new 会为内置类型分配内存。 A* p5 (A*)malloc(sizeof(A)*10); // 使用malloc申请10个A对象的内存A* p6 new A[10]; // 使用new申请10个A对象的内存数组的内存分配 malloc分配内存给10个 A 类型的对象但不会调用构造函数。new A[10]分配内存并调用构造函数为每个对象初始化。 free(p5); // 释放通过malloc分配的内存delete[] p6; // 释放通过new[]分配的内存调用每个对象的析构函数数组内存释放 free(p5)释放10个 A 类型对象的内存。delete[] p6释放通过 new[] 分配的内存确保调用每个对象的析构函数。 总结 new 和 delete vs malloc 和 free new 和 delete 用于分配和释放自定义类型的内存时会自动调用构造函数和析构函数而 malloc 和 free 只进行内存分配和释放不调用构造和析构函数。 五、operator new与operator delete函数 1. 原理 new和delete是用户进行动态内存申请和释放的操作符operator new 和operator delete是系统提供的全局函数new在底层调用operator new全局函数来申请空间delete在底层通过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); }/* 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 实际也是通过malloc来申请空间如果malloc申请空间成功就直接返回否则执行用户提供的空间不足应对措施如果用户提供该措施就继续申请否则就抛异常。operator delete 最终是通过free来释放空间的。 2. 异常捕获方法 #include iostream #include exception using namespace std;class A { public:A(int a 0) : _a(a) {cout A constructed: _a endl;}~A() {cout A destructed. endl;}private:int _a; };void Func() {int* p1 new int[1024 * 1024 * 100]; // 试图分配内存cout p1 endl;int* p2 new int[1024 * 1024 * 100]; // 试图分配内存cout p2 endl;int* p3 new int[1024 * 1024 * 100]; // 试图分配内存cout p3 endl;int* p4 new int[1024 * 1024 * 100]; // 试图分配内存cout p4 endl;int* p5 new int[1024 * 1024 * 100]; // 试图分配内存cout p5 endl; }int main() {try {Func(); // 调用函数以分配内存} catch (const exception e) {cout Memory allocation failed: e.what() endl; // 捕获异常并打印信息}return 0; }六、new和delete的实现原理 1. 内置类型 如果申请的是内置类型的空间new和mallocdelete和free基本类似 不同的地方是 new/delete申请和释放的是单个元素的空间new[]和delete[]申请的是连续空间而且new在申请空间失败时会抛异常malloc会返回NULL。 2. 自定义类型 new 和 delete 原理 操作原理说明new1. 调用 operator new通过调用 operator new 函数申请足够的内存空间。2. 执行构造函数在申请的内存空间上执行构造函数完成对象的构造并返回指向对象的指针。delete1. 执行析构函数在对象的内存空间上执行析构函数清理对象中占用的资源。2. 调用 operator delete通过调用 operator delete 函数释放对象所占用的内存空间。new T[N]1. 调用 operator new[]调用 operator new[] 函数通过实际调用 operator new 函数申请 N 个对象所需的内存空间。2. 执行 N 次构造函数在申请的内存空间上执行 N 次构造函数构造 N 个对象。delete[]1. 执行 N 次析构函数在释放的对象空间上执行 N 次析构函数清理 N 个对象中占用的资源。2. 调用 operator delete[]调用 operator delete[] 函数释放内存空间实际在 operator delete[] 中调用 operator delete 来释放内存。 七 、定位new表达式(placement-new) 使用这个的理由是我们对一个已经存在的对象不能在外面显示调用它的构造函数但是析构函数可以。 为了解决这个问题引入定位new表达式。 定位new表达式是在已分配的原始内存空间中调用构造函数初始化一个对象。 使用格式 new (place_address) type或者new (place_address) type(initializer-list) place_address必须是一个指针initializer-list是类型的初始化列表 使用场景 定位new表达式在实际中一般是配合内存池使用。因为内存池分配出的内存没有初始化所以如果是自定义类型的对象需要使用new的定义表达式进行显示调构造函数进行初始化。 class A { public:A(int a 0): _a(a){cout A(): this endl;}~A(){cout ~A(): this endl;} private:int _a; }; // 定位new/replacement new int main() {// p1现在指向的只不过是与A对象相同大小的一段空间还不能算是一个对象因为构造函数没//有执行A* p1 (A*)malloc(sizeof(A));new(p1)A; // 注意如果A类的构造函数有参数时此处需要传参p1-~A();free(p1);A* p2 (A*)operator new(sizeof(A));new(p2)A(10);p2-~A();operator delete(p2);return 0; }八、对比malloc/free和new/delete的区别 malloc/free和new/delete的共同点是都是从堆上申请空间并且需要用户手动释放。不同的地方是 malloc和free是函数new和delete是操作符malloc申请的空间不会初始化new可以初始化malloc申请空间时需要手动计算空间大小并传递new只需在其后跟上空间的类型即可如果是多个对象[]中指定对象个数即可malloc的返回值为void*, 在使用时必须强转new不需要因为new后跟的是空间的类型malloc申请空间失败时返回的是NULL因此使用时必须判空new不需要但是new需要捕获异常申请自定义类型对象时malloc/free只会开辟空间不会调用构造函数与析构函数而new在申请空间后会调用构造函数完成对象的初始化delete在释放空间前会调用析构函数完成空间中资源的清理释放 总结 到这里内存管理的东西就结束了谢谢大家~
http://www.w-s-a.com/news/890130/

相关文章:

  • 湖北网站制作公司银川网站建设哪家不错
  • 网站后台演示地址服装网站建设公司推荐
  • 湖北钟祥建设局网站旅游哪个网站最好
  • 浙江建设工程信息网站辽宁建设工程信息网场内业绩什么意思
  • 郑州做网站公司 汉狮网络专业图片搜集网站怎么做
  • 网站托管是什么品牌推广营销平台
  • 制作网站的难度贵州省兴义市建设局网站
  • 永春建设局网站室内设计师培训班学费多少
  • 做仿站如何获取网站源码windows2012做网站
  • 网站建设最好的公司东莞外贸网站
  • 普兰店网站建设一般做网站什么价格
  • 网站建设的发展目标甘肃网站设计公司
  • 常州西站建设规划室内装修设计学校哪里好
  • 大连网站制作选择ls15227如何编辑网站
  • 网站发稿平台迪士尼网站是谁做的
  • 常州有哪些好的网站建设案例wordpress 360 插件
  • 模板网站有后台么柳城网站建设
  • 地方门户网站制作一级做c爱片的网站
  • 自己上传图片做动漫图网站北京福田汽车
  • 一级a做爰片免费网站录像ps做网站图片水印
  • 网页广告投放成都优化推广公司
  • 网站开发 印花税网页制作站点
  • 创建个人网站有什么好处国外建站系统
  • 桂林学校网站制作2018年网站设计公司
  • 建网站不想用怎样撤销搜狗收录提交入口网址
  • 做简单网站需要学什么软件有哪些南通优普网站建设
  • 网站排版尺寸湖北交投建设集团集团网站
  • 南京网站设计公司有哪些公司看动漫是怎么做视频网站
  • vs做网站怎么做窗体怎么在电脑上自己做网站吗
  • 做网站应该学什么网站编程 外包类型