是否能够直接操作内存资源,不同的程序语言有不同的选择(语法机制),有的程序语言(如C#和Java)有垃圾回收机制,而C因为效率和便利的考虑,能够通过指针操作内存资源,且无垃圾回收机制。C++延续C的效率原则,但在指针的安全使用方面做了努力,引入了引用、异常处理机制,通过newdelete封装了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(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; igo();
	delete p;//如果go()抛出异常,delete得不到执行从而产生内存泄露
}
void notleaky()
{
	unique_ptr 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-

限 时 特 惠: 本站每日持续更新海量各大内部创业教程,一年会员只需98元,全站资源免费下载 点击查看详情
站 长 微 信: muyang-0410