无用单元和悬挂引用

Posted 郑哲

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了无用单元和悬挂引用相关的知识,希望对你有一定的参考价值。

1.无用单元:

指一块存储区(或资源),该存储区虽然是程序(或进程)的一部分,但是在程序中却不可再对其引用。

按照C++的规定,我们可以说,无用单元是程序中没有指针指向的某些资源;

例如:

1 void main()
2 {
3     char *p = new char[1000];//分配一个包含1000个字符的动态数组
4     char *q = new char[1000];//另一个动态内存
5     p = q;//将p和q进行一些操作的代码
6     /*p所指向的1000个字符的存储区会发生什么?此时,p和q指向相同的区域,没有指针指向之前p指向
7     的旧存储区!该存储区还在,仍然占用着空间。但是程序已经不能访问该区域*/
8 }

 

2.悬挂引用:

当两个指针同时指向一个地址时,通过一个指针删除了该地址的数据,另一个指针就产生了悬挂引用。

1 void main()
2 {
3     char *p;
4     char *q;
5     p = new char[1024];
6     q = p;
7     delete[]p;
8     p = 0;//现在q就是一个悬挂引用
9 }

无用单元控制再软件设计中时一个非常重要的问题,因为它会影响应用的整体性能。

即使是不太重要的应用程序,再持续运行一段时间未停止,内存泄露也会导致严重的问题。

随着越来越多的内存变成无用单元,应用程序(和整个系统)的性能逐渐降低,导致越来越多的虚拟内存分页活动。最终,由于分页文件被占满,

整个系统只能停止。

并非所有程序都可以随意暂停,如核电站控制程序,一旦暂停可能将导致灾难性的后果。

 

 

 

C++在何时产生无用单元:

1.从函数退出时,在函数内部创建的所有局部变量(包括对象)以及按值传递的所有参数都不可访问。

2.从块退出时,在块内部声明的所有局部变量(包括对象)都不可访问

3.任何复杂表达式包含的临时变量,在不需要时必须全部予以销毁,否则它们将成为无用单元。

4.任何动态分配的对象,在不需要时必须由程序员显式地销毁。

 

 1 TPerson::TPerson(const char _birthData[])
 2     :birthData(_birthData),address(0)
 3 {}
 4 
 5 char *strdup(const char* src)   //辅助函数
 6 {
 7     char *ptr = new char[strlen(src) + 1];
 8     strcpy(ptr, src);
 9     return ptr;
10 }
11 
12 TPerson::TPerson(const char _theName[], const char _theAddress[], unsigned long _theSSN, const char _theBirthDate[])
13     :ssn(theSSN), birthDate(_theBirthDate)
14 {
15     name = (_theName ? strdup(theName) : 0);
16     address = (_theAddress ? strdup(_theAddress) : 0);
17 }

辅助函数为数据成员申请一个新的内存空间。

无用单元的收集:

不仅只是析构函数来回收内存,一般函数也要回收内存。

1.析构函数

1 TPerson::~TPerson()
2 {
3     delete[]name;
4     delete[]address;
5 }

 2.成员函数

 1 void TPerson::SetName(const char newName[])
 2 {
 3     unsigned oldLength = name ? strlen(name) : 0;
 4     unsigned newLength = newName ? strlen(newName) : 0;
 5     if (oldLength < newLength)
 6     {
 7         delete[]name;     //无用单元收集
 8         name = (newName ? strdup(newName) : 0);
 9     }
10     else
11     {
12         if (newName) strcpy(name, newName);
13         else { delete[]name; name = 0; }
14     }
15 }

 

 

内嵌对象,在主对象即将被销毁时,调用内嵌对象的析构函数,所有可以防止内存泄露。

以上是关于无用单元和悬挂引用的主要内容,如果未能解决你的问题,请参考以下文章

Max 函数的 6 种操作方法:API设计悬挂引用以及C++20 constraints

iOS - 未解决的错误导致崩溃:悬挂对无效对象的引用

4.2Android Studio压缩你的代码和资源

BEAM188和LINK180简单实例

Android App 在片段中创建 ListView 引用时关闭

片段对话框对活动的松散引用