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

安徽全过程网站搭建案例美食网页设计图

安徽全过程网站搭建案例,美食网页设计图,wordpress shell,如何建立自己的网站去推广就是你被爱情困住了#xff1f;Wake up bro#xff01; 文章目录一、C/C内存分布二、C语言中动态内存管理方式三、C中内存管理方式1.new和delete操作内置类型2.new和delete操作自定义类型#xff08;仅限vs的底层实现机制#xff0c;new和delete一定要匹配使用#xff0c;…就是你被爱情困住了Wake up bro 文章目录一、C/C内存分布二、C语言中动态内存管理方式三、C中内存管理方式1.new和delete操作内置类型2.new和delete操作自定义类型仅限vs的底层实现机制new和delete一定要匹配使用否则会出现各种各样的情况四、operator new和operator delete函数实际是封装了malloc和_free_dbg函数1.malloc和new的区别malloc失败返回NULL。new失败抛异常捕获错误不需要检查返回值。2.operator new operator delete调用new和delete实际上是调用系统提供的这两个全局函数五、new和delete的实现原理new、new T[N]、delete、delete[ ]的实现原理六、定位new表达式(placement-new) 初始化内存池分配出来的内存空间七、常见面试题1. malloc/free和new/delete的区别从用法功能和底层两个角度来回答2.内存泄露除定义和危害外其他知识了解即可2.1 内存泄露的定义和危害是指针丢了而不是内存丢了2.2 内存泄露的分类2.3 如何检测内存泄露2.4 如何避免内存泄露一、C/C内存分布 1. 站在语言级别的角度来看数据段其实更喜欢被叫做静态区因为这个区域存放的都是静态数据和全局数据其中数据段还可以细分为BSS段和data段代码段被叫做常量区其中存放了机器码和一些只读常量例如常量字符串这些。 站在系统级别看待内存分布虚拟地址空间 2. 栈又叫堆栈 — 非静态局部变量/函数参数/返回值等等栈是向下增长的。 内存映射段 — 是高效的I/O映射方式用于装载一个共享的动态内存库。用户可使用系统接口创建共享内存做进程间通信。 堆 — 用于程序运行时动态内存分配堆是可以上增长的。 数据段 — 存储全局数据和静态数据。 代码段 — 可执行的代码/只读常量。 3. 下面给大家分享了许多大佬的文章关于计算机内存大小计算字、字长、字节、字位的以及计算机组成原理部分的知识有关于地址总线等等知识这些知识了解即可博主不是搞硬件的所以给大家推送几篇文章我们一起扩展一下知识。 所以指针大小固定的原因就是无论你是什么类型的指针指针变量中存储的就是字的地址因为虚拟地址空间或物理地址都是用字来作为自然的数据单位一个字在32位机器上就是4Byte大小所以可见指针大小在32位机器上就是4Byte。 字长、字节、字、字位的区别转载自csdn博主gxhlh的文章 在32位机器中一个字包含32个元器件那么总共就有4×8×1024×1024×1024个元器件也就是4G大小的内存如果是64位机器下理想情况下一个字包含64个元器件也就是一个字的元器件排列可能有2的64次方中可能2的32次方下就已经有4G多的元器件了如果是2的64次方那就是2的32次方再×4G大小也就是非常非常多的元器件。很多人容易算成16G大小的元器件这实际上是错误的他们以为2的64次方是4G×4G但显然不是这样计算的因为m×m变成平方了都4G×4G之后的单位怎么可能还是G所以有不少人以为64位机器的内存是16G这显然是错误的。 实际中的32位机器下一个字不是64个元器件地址总线并非64根而是36根或40根如果真有64根内存都大到天上去了。 关于地址总线、32位和64位系统区别的文章转载自简书博主gsonliu的文章 4. 对于全局数据、静态全局数据、局部静态数据他们都存放在静态区中非静态局部变量以及数组这些都是存放在栈区上的。 而char2数组中的内容实际上是从常量区中的常量字符串拷贝过来的所以* char2指向的不是常量区中的字符a指向的是栈区中拷贝到数组char2里面的字符串中的字符a。至于指针变量pChar3本身就在栈区上只是这个变量内部存储的是常量区abcd字符串的首字符a的地址所以pChar3就存在常量区里面了。 同理ptr1也是指针变量在栈区里面其中存放的也是堆区开辟好空间的首字符的地址所以ptr1在堆区上。 sizeof求的是变量类型所占空间的大小如果是数组则求的是数组所占空间大小数组末尾的\0也会计算指针大小取决于机器的位数32位则为4字节64位则为8字节。strlen求的是字符串有效长度不包括末尾的\0。 二、C语言中动态内存管理方式 void Test () {int* p1 (int*) malloc(sizeof(int));free(p1);// 1.malloc/calloc/realloc的区别是什么int* p2 (int*)calloc(4, sizeof (int));int* p3 (int*)realloc(p2, sizeof(int)*10);// 这里需要free(p2)吗free(p3 ); }1. malloc就是简单的向堆区申请空间资源calloc不仅会申请资源还会将申请的空间内容初始化为0calloc malloc memset设置为0realloc用于空间的扩容如果空间不够我们可以利用realloc再向堆区申请扩大空间扩容又分为异地扩容和原地扩容两种方式如果是原地扩容则p3和p2指向的是同一块空间所以不同重复释放p2指向的空间如果是异地扩容则p2和p3指向的空间都需要释放当然上述代码realloc的空间很小一定是原地扩容所以不需要释放p2当申请空间过大时才可能出现异地扩容的情况。 2. malloc的实现原理 glibc中malloc实现原理 三、C中内存管理方式 1.new和delete操作内置类型 1. 申请一个空间什么都不用带初始化用( ) 申请多个空间用[ ]初始化用{ }。 delete[ ]用于释放开辟个数大于1的空间delete用于释放仅仅开辟个数为1的空间。 #include iostream using namespace std; int main() {// 内置类型// 相比malloc和free除了用法有区别之外没有其他区别int* p1 new int;//不带初始化delete p1;int* p2 new int(0);//将申请的int空间初始化为0delete p2;int* p3 new int[10];//一次申请10个int大小的空间delete[]p3;int* p4 new int[10] {1, 2, 3, 4, 5};//申请10个int大小的空间并将其进行初始化后面的自动初始化为0delete[]p4;return 0; }2.new和delete操作自定义类型仅限vs的底层实现机制new和delete一定要匹配使用否则会出现各种各样的情况 class A { public:A(int a 0): _a(a){cout A(): this endl;}//是否屏蔽掉显示的析构函数决定了delete和new不匹配是否出现错误的问题。~A(){cout ~A(): this endl;} private:int _a; }; struct ListNode {ListNode* _next;int _value;ListNode(int value 0)//缺省值搞成0:_next(nullptr), _value(value){} }; int main() {//对于自定义类型new和delete除了空间管理申请和释放之外还会调用构造和析构函数。//new实际就是为自定义类型准备的A* p1 new A;// new会调用构造函数A* p2 (A*)malloc(sizeof(A));delete p1;// delete会调用析构函数free(p2);ListNode* n1 new ListNode(1);ListNode* n2 new ListNode(2);ListNode* n3 new ListNode(3);ListNode* n4 new ListNode(4);n1-_next n2;n2-_next n3;n3-_next n4;//new和delete一定要匹配正确否则可能会出现意想不到的错误这些错误和newdelete的底层实现机制有关系。A* p3 new A;delete[]p3;//这样就会出现意料不到的错误我的编译器出现了死循环疯狂调用析构函数停不下来根本。//delete p3;//这样的匹配方式是正确的。A* p4 new A[10];delete p4;//如果存在显示的析构函数则会报内存泄露的错误。如果屏蔽掉显示的析构函数则编译器不会报错。A* p5 new A;delete[]p5;//析构函数放出来会报错不放出来就不会报错。//delete会向前找一个位置然后开始释放空间则一定会报错。//析构函数放出来编译器会以为你释放的是多个空间所以就会去向前找存放的数字但其实前面并没有开辟空间所以就会报错。//析构函数不放出来编译器会很智能的从当前位置向后释放空间不会向前找那一个空间所以不会报错。return 0; }1. 在申请自定义类型空间时new会调用构造函数delete调用析构函数malloc和free不会调用。 2. new和delete一定要匹配比如new和delete[ ]匹配了或者new[10]和delete匹配了有可能出现内存泄露和报错等问题这些问题都是依赖于编译器的底层实现机制在释放空间时delete可能知道要释放多少字节的空间但具体要释放多少个对象编译器是不知道的因为编译器无法确定类的大小也就无法知道对象具体所占字节的大小所以在vs的底层实现上new开辟空间的时候会在开辟空间的前面多开辟一个空间用于存储开辟的空间中具体对象的个数然后在返回指针的时候会将指针向后挪动直到指向开辟的有效可用的空间等到释放空间的时候指针又会向后挪动这样编译器就知道具体要释放多少个对象了也就是调用多少次析构函数最后将开辟的所有的空间都给释放掉包括前面多开辟的一个空间。 3. delete只会从指针的当前位置开始释放空间并不会先向前挪动指向空间的最开始位置所以new[10]和delete匹配会发生内存泄露因为new[10]不仅仅会开辟10个对象大小空间还会多开辟一个存储对象大小的空间而delete释放的时候不会自动向前挪动只有delete[ ]释放时才会向前挪动。 但是我们看到当显示的析构函数屏蔽掉时编译器就不会报错了这是因为如果显示写析构函数编译器会觉得我们的意图是想知道释放空间时具体要释放多少个对象所以new会多开辟一个空间。而不显示写析构函数编译器就会很智能它觉得我们不想知道具体要释放多少个对象所以就不会多开辟一个空间此时正好就可以将所有空间释放掉。 4. 而new和delete[ ]匹配的话并且有显式定义的析构函数一定会报错因为编译器以为new多开辟了一个空间用于存储对象个数所以delete[ ]释放的时候会自动将指针前挪从前面开始释放空间这样就发生了越界访问前面空间里面存的是什么是不确定的所以编译器会死循环调用析构函数这就是越界访问给我们带来的未知预料错误。 而如果屏蔽显式定义的析构函数的话编译器就不会多开辟一个空间并且delete[ ]也不会从前面开始释放空间因为编译器已经向delete[ ]表明意图告诉delete[ ]不需要多释放前面那个空间因为new的时候就没有多开辟那个空间所以也就不会报错。 四、operator new和operator delete函数实际是封装了malloc和_free_dbg函数 1.malloc和new的区别malloc失败返回NULL。new失败抛异常捕获错误不需要检查返回值。 void Test() {while (1){//new失败抛异常 --- 不需要检查返回值char* p1 new char[1024 * 1024 * 1024];//一次申请1G的空间快速显示申请失败的结果//char* p1 (char*)operator new(1024 * 1024 * 1024);//和malloc使用形式相似但它申请失败是抛异常而不是返回空指针cout (void*)p1 endl;//强转打印p1指针的地址否则cout打印的是字符串//所以用习惯new之后就不想用malloc了自定义类型会调用构造和析构内置类型用起来更加简洁不需要检查错误等等优点更方便一些} } int main() {while (1){//malloc失败会返回空指针所以我们需要在malloc之后进行if判断检测空间是否申请成功int* p1 (int*)malloc(1024*100);//一次申请100KB的空间if (p1){cout p1 endl;}else{cout 申请失败 endl;break;}}try//捕获异常有异常则直接跳转到catch{Test();}catch (exception e)//如果new失败则直接会抛异常代码执行位置直接跳转到catch也就是捕获错误的位置。{cout e.what() endl;}A* p1 new A[10];//delete[] p1;//下面这俩殊途同归free(p1);//在析构函数未显示实现的情况下用free也不会发生内存泄露//因为delete和free底层调用的都是_free_dbgreturn 0; }1. malloc失败返回空指针new失败抛异常异常是面向对象语言处理错误的一种方式new失败调试光标从当前位置会直接跳转到catch部分也就是捕获错误的地方。所以使用new不需要判断返回值直接用捕获错误的方式抛异常即可。 2.operator new operator delete调用new和delete实际上是调用系统提供的这两个全局函数 1. new申请内存的底层机制是operator newoperator new的底层又是malloc实现的operator new不是new的运算符重载因为运算符重载的目的是让自定义类型能够像内置类型一样使用而内置类型的原生符号里面是没有new的由此可见operator new不是运算符重载。 所以operator new和operator detele是系统提供的全局函数在库里面实现的。另一方面运算符重载的operator和运算符是连在一起的而这两个全局函数的opsrator和new或delete是分开的这也可以帮助我们区分。 2. 下面这段代码是C库中的代码从operator new的参数可以看出他是没有this指针的由此可以证明这个函数一定不是运算符重载因为运算符重载都是非静态类成员函数是有this指针的。 /* operator new该函数实际通过malloc来申请空间当malloc申请空间成功时直接返回 申请空间失败尝试执行空间不足应对措施如果改应对措施用户设置了则继续申请否则抛异常。 */ void *__CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc) { // try to allocate size bytesvoid *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_FINALLYreturn; } /* free的实现 */ #define free(p) _free_dbg(p, _NORMAL_BLOCK)3. 通过上述两个全局函数的实现知道operator new 实际也是通过malloc来申请空间如果malloc申请空间成功就直接返回否则执行用户提供的空间不足应对措施如果用户提供该措施就继续申请否则就抛异常。operator delete 最终是通过free来释放空间的。 4. 所以operator new其实是malloc的封装申请内存失败会抛异常这样才符合C面向对象处理错误的方式。operator delete也是free的封装free是一个宏函数等效于_free_dbg。 从new的反汇编代码可以看到new底层的确是调用call了operator new全局函数 delete和free底层调用的都是_free_dbg函数所以在析构函数未显示实现的情况下delete和free实际上没有区别因为释放空间都是从当前位置向后释放。 五、new和delete的实现原理new、new T[N]、delete、delete[ ]的实现原理 1. 下面是关于函数的实现原理帮助我们更好的理解new、new T[N]、delete、delete[ ]这些函数。 2. 下面拿new来举例从汇编角度可以看到operator new和operator new[ ]函数的调用其实operator new[ ]也要调用operator new函数而operator new的底层又会调用mallocoperator new就是malloc的封装。 六、定位new表达式(placement-new) 初始化内存池分配出来的内存空间 1. 定位new表达式是在已分配的原始内存空间中调用构造函数初始化一个对象。 2. 使用格式 new (place_address) type或者new (place_address) type(initializer-list) place_address必须是一个指针initializer-list是类型的初始化列表 class A { public:A(int a 0): _a(a){cout A(): this endl;}~A(){cout ~A(): this endl;} private:int _a; }; int main() {A* p1 new A;//A* p2 new A[10];A* p3 (A*)malloc(sizeof(A));if (p3 nullptr){perror(malloc fail\n);exit(-1);}//定位new --- 对p3所指向空间显示调用构造函数初始化new(p3)A(1);//下面这两种释放空间的方式都可以p3-~A();//析构函数可以显示调用构造函数不能显示调用free(p3);delete p3;//delete 析构 operator delete函数底层还是_free_dbg和free一样的底层函数return 0; }3. 如果特别不想使用new抛异常的方式可以使用定位new表达式然后显式调用构造函数来替代new抛异常。但是吧这样的使用方式太挫了寂然一行代码可以解决的问题我为什么还要先malloc在定位new表达式将已开辟空间初始化呢这不是把原来一步就可以完成的工作硬生生拆分为两步吗这样的使用方式简直太挫了。 然而定位new表达式在实际中一般是配合内存池使用。因为内存池分配出的内存没有初始化所以如果是自定义类型的对象需要使用new的定位表达式来显示调用构造函数进行对象的初始化。 4. 我们可以把malloc或new开辟的空间比喻为村口的一口井所有村民都需要每天去井那里打水而内存池就相当于村长家的蓄水池这个蓄水池有一根管道直接连接到村口的井所以对于村长来说池化技术大大提高了村长家的效率。 池化技术转载自腾讯云开发者社区博主用户5325874的文章 什么是池化技术转载自csdn博主风神修罗使的文章 七、常见面试题 1. malloc/free和new/delete的区别从用法功能和底层两个角度来回答 相同点 malloc/free和new/delete的共同点是都是从堆上申请空间并且需要用户手动释放。 不同点 1.用法功能 a.malloc和free是函数new和delete是操作符 b.对于自定义类型malloc申请的空间不会初始化new可以初始化 c.malloc申请空间时需要手动计算空间大小并传递new只需在其后跟上空间的类型即可如果是多个对象[]中指定对象个数即可 d.malloc的返回值为void*, 在使用时必须强转new不需要因为new后跟的是空间的类型 2.底层 a. 申请自定义类型对象时malloc/free只会开辟空间不会调用构造函数与析构函数而new在申请空间后会调用构造函数完成对象的初始化delete在释放空间前会调用析构函数完成空间中资源的清理 b.malloc申请空间失败时返回的是NULL因此使用时必须判空new不需要但是new需要捕获异常 2.内存泄露除定义和危害外其他知识了解即可 2.1 内存泄露的定义和危害是指针丢了而不是内存丢了 1. 什么是内存泄漏内存泄漏指因为疏忽或错误造成程序未能释放已经不再使用的内存的情况。内存泄漏并不是指内存在物理上的消失而是应用程序分配某段内存后因为设计错误失去了对该段内存的控制因而造成了内存的浪费。 2. 内存泄漏的危害长期运行的程序出现内存泄漏影响很大如操作系统、后台服务等等出现内存泄漏会导致响应越来越慢最终卡死。 3. 一般出现内存泄露有两种情况一种是我们手动申请了但由于疏忽导致忘记释放了指针指向的内存另一种是由于某些原因例如抛异常代码跳转导致错过执行了释放空间的代码。 void MemoryLeaks() {// 1.内存申请了忘记释放int* p1 (int*)malloc(sizeof(int));int* p2 new int;// 2.异常安全问题int* p3 new int[10];Func(); // 这里Func函数抛异常导致 delete[] p3未执行p3没被释放.delete[] p3; }2.2 内存泄露的分类 C/C程序中一般我们关心两种方面的内存泄漏 1.堆内存泄漏(Heap leak) 堆内存指的是程序执行中依据须要分配通过malloc / calloc / realloc / new等从堆中分配的一块内存用完后必须通过调用相应的 free或者delete 删掉。假设程序的设计错误导致这部分内存没有被释放那么以后这部分空间将无法再被使用就会产生Heap Leak。 2.系统资源泄漏 指程序使用系统分配的资源比方套接字、文件描述符、管道等没有使用对应的函数释放掉导致系统资源的浪费严重可导致系统效能减少系统执行不稳定。 2.3 如何检测内存泄露 1. 在vs下可以使用windows操作系统提供的_CrtDumpMemoryLeaks() 函数进行简单检测该函数只报出了大概泄漏了多少个字节没有其他更准确的位置信息。 int main() {int* p new int[10];// 将该函数放在main函数之后每次程序退出的时候就会检测是否存在内存泄漏_CrtDumpMemoryLeaks();return 0; }// 程序退出后在输出窗口中可以检测到泄漏了多少字节但是没有具体的位置 Detected memory leaks! Dumping objects - {79} normal block at 0x00EC5FB8, 40 bytes long. Data: CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD Object dump complete.2. 因此写代码时一定要小心尤其是动态内存操作时一定要记着释放。但有些情况下总是防不胜防简单的可以采用上述方式快速定位下。如果工程比较大内存泄漏位置比较多不太好查时一般都是借助第三方内存泄漏检测工具处理的。 在linux下内存泄漏检测linux下几款内存泄露检测工具 在windows下使用第三方工具VLD工具说明 其他工具内存泄露工具比较 2.4 如何避免内存泄露 1.工程前期良好的设计规范养成良好的编码规范申请的内存空间记着匹配的去释放。ps这个理想状态。但是如果碰上异常时就算注意释放了还是可能会出问题。需要下一条智能指针来管理才有保证。 2.采用RAII思想或者智能指针来管理资源。 3.有些公司内部规范使用内部实现的私有内存管理库。这套库自带内存泄漏检测的功能选项。 4.出问题了使用内存泄漏工具检测。ps不过很多工具都不够靠谱或者收费昂贵。 总结一下: 内存泄漏非常常见解决方案分为两种 1、事前预防型。如智能指针等。2、事后查错型。如内存泄漏检测工具。
http://www.w-s-a.com/news/135850/

相关文章:

  • 网站空间支持什么程序工作服款式
  • 网站单页品牌网站建设 蝌蚪5小
  • 怎么做外贸网站需注意哪些做电脑系统的网站
  • 网站建设介绍推广用语河南网站优化外包服务
  • 课程网站模板贵州省城乡与建设厅网站
  • 网站模板及源码谁家网站用户体验做的好
  • 做网站的技术要求搜索栏在wordpress菜单上位置
  • 如何给网站弄ftpwordpress怎么添加关键词描述
  • 成都工程建设信息网站金科网站建设
  • 传媒公司 网站开发厦门网站建设门户
  • 宿城区建设局网站做网站的绿色背景图
  • 网站空间托管合同 .doc网站开发团队 组建
  • 网站建设书本信息it运维服务
  • 四核网站建设设计网站流程
  • ui设计网站设计与网页制作视频教程wordpress插件漏洞利用
  • 网站建设公司排名前十做网站的最终目的
  • 选择网站开发公司的标准中国网站建设市场规模
  • 衣服网站建设策划书广州住房和城乡建设部网站
  • 微商城科技淄博网站建设优化seo
  • 杭州 网站设计制作东圃手机网站开发
  • 网站文章页内链结构不好可以改吗微信平台如何开发
  • 炫酷业务网站课程网站如何建设方案
  • 网站建设服务器可以租吗wordpress微信打赏
  • 网站制作的重要流程图大连网站优化快速排名
  • 河南省住房建设厅官方网站注册公司邮箱需要什么
  • 美橙网站注册华为手机网站建设策划方案论文
  • 河南省和建设厅网站首页在线图片翻译
  • 关于备案空壳网站清理通知去别人网站挂黑链
  • 做网站待遇世界购物平台排行榜
  • 售后服务网站什么网站免费做简历模板