是否能够直接操作内存资源,不同的程序语言有不同的选择(语法机制),有的程序语言(如C#和Java)有垃圾回收机制,而C因为效率和便利的考虑,能够通过指针操作内存资源,且无垃圾回收机制。C++延续C的效率原则,但在指针的安全使用方面做了努力,引入了引用、异常处理机制,通过new\delete封装了malloc()\free(),且在STL封装了智能指针。
标记(mark)和清扫(sweep)是一种垃圾回收方法。使用这种方法的垃圾回收器定期检查程序中的每个指针,并将指针引用的内存标记为仍在使用。在每一轮周期结束时,未标记的内存视为没有在使用,因而被释放。
a 在垃圾回收器中注册所有指针,这样就可以进行遍历操作;
b 让所有对象都从一个混入类中派生,允许垃圾回收器将对象标记为正在使用;
c 确保垃圾回收器运行时不能修改指针;
垃圾回收可能也会引发一些问题,如当垃圾回器运行时,程序可能会停止响应。析构函数具有不确定性。
对于“裸指针”,从声明、定义、分配、初始化、访问、释放、置NULL的整个过程都有可能发生错误:
// 1 访问错误 // 1.1 内存分配未成功,却使用了它 void allocatedMayFailure() { int* arr = new int[1000000000]; // may return nullptr if(arr==NULL) return; arr[0] = 1; cout<<arr[0]; delete[] arr; } // 1.2 访问非法指针 void accessInvalid() { int* p = reinterpret_cast<int*>(1000); *p = 5; // bug, p is not a valid pointer, crash! } // 1.3 内存分配虽然成功,但是尚未初始化就引用它 void readUninitialized() { int* p; cout<<*p; // bug, p is uninitialized } // 1.4 内存分配成功并且已经初始化,但操作越过了内存的边界 void accessElsewhere() { int x, y[11], z; x=0; z=0; for(int i=0; i<=11; i++) { y[i] = 5; // bug for i==11, element 11 is past end of array } } // 1.5 非法访问已释放指针 void accessFreed() { int* p1 = new int; delete p1; int* p2 = new int; *p1 = 5; // bug, the memory pointed to by p1 has been freed } // 2 内存释放错误 // 2.1 忘记了释放内存,造成内存泄露 void memoryLeak() { int* p = new int[1000]; return; // Bug, not freeing p } // 2.2 重复释放内存错误 void doubleFree() { int* p1 = new int[1000]; delete[] p1; int* p2 = new int[1000]; delete[] p1; // bug, freeing p1 twice,crash! } // 2.3 释放内存命令与分配内存命令不匹配 void mismatchedFree() { int* p1 = (int*)malloc(sizeof(int)); int* p2 = new int; int* p3 = new int[1000]; delete p1; // bug, should use free() delete[] p2; // bug, should use delete free(p3); // bug, should use delete[] } //2.4 因为异常机制,释放内存语句没有机会执行 class Simple { public: void go(){} }; void leaky() { Simple* p = new Simple(); p->go(); delete p;//如果go()抛出异常,delete得不到执行从而产生内存泄露 } void notleaky() { unique_ptr<Simple> p(new Simple()); //c+11 p->go(); } // 2.5 使用 free 或 delete 释放了内存后,没有将指针设置为 NULL。 // 导致产生" 野指针"(指向的内存是已被操作系统回收的指针)。 void noNull() { char* p = new char[10]; memset(p,0,10); delete [] p; //p=NULL; // 指针释放后记得赋NULL值 if(p!=NULL) { strcpy(p,"hello!"); // 使用悬空指针(野指针) cout<<p; } } //2.6 释放堆上指针 void freeStack() { int x; int* p = &x; delete p; // bug, freeing stack memory, crash! }
-End-
本文暂时没有评论,来添加一个吧(●'◡'●)