zoukankan      html  css  js  c++  java
  • [Swift通天遁地]七、数据与安全-(11)如何检测应用程序中的内存泄露

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
    ➤微信公众号:山青咏芝(shanqingyongzhi)
    ➤博客园地址:山青咏芝(https://www.cnblogs.com/strengthen/
    ➤GitHub地址:https://github.com/strengthen/LeetCode
    ➤原文地址:https://www.cnblogs.com/strengthen/p/10331948.html 
    ➤如果链接不是山青咏芝的博客园地址,则可能是爬取作者的文章。
    ➤原文已修改更新!强烈建议点击原文地址阅读!支持作者!支持原创!
    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★

    目录:[Swift]通天遁地Swift

    本文将演示使用Instruments Allocations工具检测应用程序中的内存泄漏问题。

    内存溢出 out of memory:是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;比如申请了一个integer,但给它存了long才能存下的数,那就是内存溢出。

    内存泄露 memory leak是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。

    在项目文件夹【DemoApp】上点击鼠标右键,弹出右键菜单。

    【New File】->【Swift File】->【Next】->【Save As】:People.swift->【Create】

     1 import Foundation
     2 //主人类
     3 class People
     4 {
     5     //名称属性
     6     var name : String
     7     //主人的宠物
     8     var pet : Pet?
     9     
    10     //添加一个初始化方法,并以名称作为参数
    11     init(name:String)
    12     {
    13         //设置对象的名称属性
    14         self.name = name
    15         //初始化日志
    16         print("People is initialized.")
    17     }
    18     
    19     //添加一个析构方法
    20     deinit
    21     {
    22         //析构日志
    23         print("People is deinitialized.")
    24     }
    25 }

    使用相同的方式创建另一个类文件【Pet.swift】 

     1 import Foundation
     2 //宠物类
     3 class Pet
     4 {
     5     //名称属性
     6     var name : String
     7     //宠物的主人属性
     8     var master : People?
     9     
    10     //添加一个初始化方法,并以名称作为参数
    11     init(name:String)
    12     {
    13         //设置名称属性
    14         self.name = name
    15         //输出初始化日志
    16         print("Pet is initialized.")
    17     }
    18     
    19     //添加一个析构方法
    20     deinit
    21     {
    22         //析构日志
    23         print("Pet is deinitialized.")
    24     }
    25 }

    在项目导航区,打开视图控制器的代码文件【ViewController.swift】 

     1 import UIKit
     2 
     3 class ViewController: UIViewController {
     4 
     5     override func viewDidLoad() {
     6         super.viewDidLoad()
     7         // Do any additional setup after loading the view, typically from a nib.
     8         
     9         //添加一个按钮,当用户点击该按钮时,创建主人对象和宠物对象。
    10         let button = UIButton(frame: CGRect(x: 0, y: 0,  280, height: 44))
    11         //将按钮控件放置在根视图的中心位置
    12         button.center = self.view.center
    13         //设置正常状态下的标题文字
    14         button.setTitle("PeopleAndPet", for: .normal)
    15         //设置按钮的背景颜色为橙色
    16         button.backgroundColor = UIColor.orange
    17         //给按钮绑定点击事件
    18         button.addTarget(self,
    19                          action: #selector(ViewController.peopleAndPet), 
    20                          for: UIControl.Event.touchUpInside)
    21         
    22         //设置根视图的背景颜色
    23         self.view.backgroundColor = UIColor.orange
    24         //并把按钮控件添加到根视图
    25         self.view.addSubview(button)
    26     }
    27     
    28     //添加一个方法,用来响应按钮的点击事件
    29     @objc func peopleAndPet()
    30     {
    31         //添加一个主人对象和一个宠物对象
    32         var master:People?
    33         var dog:Pet?
    34         
    35         //对两个对象进行初始化操作,并设置它们的名称属性。
    36         master = People(name: "Jerry")
    37         dog = Pet(name: "Dog")
    38         
    39         //设置主人的宠物属性
    40         //设置宠物的主人属性
    41         //使两个对象相互引用,
    42         //由于两个对象互相引用,所以两个对象并不会在内存中被释放。
    43         master!.pet = dog        
    44         dog!.master = master       
    45 
    46         //将两个对象置空
    47         master = nil
    48         dog = nil
    49     }
    50 
    51     override func didReceiveMemoryWarning() {
    52         super.didReceiveMemoryWarning()
    53         // Dispose of any resources that can be recreated.
    54     }
    55 }

    启动按钮右下角箭头选择:【Build for Profiling】性能分析构建选项

    此时将进入性能分析窗口,在【Instrument Detail】过滤输入框内,输入类名:People

    由于尚未创建主人对象,所以在内存分配摘要列表中的搜索结果为空。

    使用【Alt】+【Tab】切换至自动打开的模拟器窗口,

    点击模拟器中创建的应用程序按钮。

    由于两个对象互相引用,所以两个对象并不会在内存中被释放。

    此时在内存分配摘要列表中,显示了一条主人对象的内存分配记录。

    选择该条内存分配记录。点击右侧的小箭头,显示内存分配的地址信息。

    接着选择内存地址,点击右侧的【扩展细节图标】(感叹号样式)。

    在列表中显示的堆栈序列,其中黑色的代码为开发者编写的代码。

    鼠标双击黑色的代码,在左侧区域显示该代码。

    点击代码界面右上角的开发软件图标,,打开Xcode.

    现在来修改People类,将Pet对象的引用修改为弱引用,

    以解决内存泄露的问题。

     1 import Foundation
     2 //主人类
     3 class People
     4 {
     5     //名称属性
     6     var name : String
     7     //主人的宠物
     8     //将宠物对象的引用修改为弱引用。
     9     //就不会产生内存泄露的问题。
    10     weak var pet : Pet?
    11     
    12     //添加一个初始化方法,并以名称作为参数
    13     init(name:String)
    14     {
    15         //设置对象的名称属性
    16         self.name = name
    17         //初始化日志
    18         print("People is initialized.")
    19     }
    20     
    21     //添加一个析构方法
    22     deinit
    23     {
    24         //析构日志
    25         print("People is deinitialized.")
    26     }
    27 }

    在【Instrument Detail】过滤输入框内,输入类名:People

    在内存分配摘要列表中,显示的搜索结果为空。

    说明People对象和Pet对象,已经在内存中被正确的释放。

    在默认情况下,显示的是已创建和被持有的内存分配,

    勾选【Allocation Lifespan】区域的【All Allocations】所有的内存分配选项。

    点击右侧的小箭头,显示内存分配的地址信息。

    继续点击内存地址右侧的小箭头,查看内存分配的详细信息。

    在内存分配列表中,显示了内存空间的创建时间,以及其他相关的信息。

    选择【Static】->【Allocations List】内存分配列表选项。

    然后在搜索框内,继续添加Pet类名。

    点击输入框左侧的下拉箭头,弹出选项列表。

    选择【Matches Any】匹配任意选项,查找和People对象和Pet对象有关的内存分配记录。

    点击【Detail】细节标签,显示选项的列表。选择【Console】控制台选项。查询内存分配的日志信息,

    此时在控制台输出了People对象和Pet对象,两者内存分配和回收的详细流水记录。

  • 相关阅读:
    Window 窗口类
    使用 Bolt 实现 GridView 表格控件
    lua的table库
    Windows编程总结之 DLL
    lua 打印 table 拷贝table
    使用 xlue 实现简单 listbox 控件
    使用 xlue 实现 tips
    extern “C”
    COleVariant如何转换为int double string cstring
    原来WIN32 API也有GetOpenFileName函数
  • 原文地址:https://www.cnblogs.com/strengthen/p/10331948.html
Copyright © 2011-2022 走看看