内存管理:内存泄漏和空悬指针

********内存管理基础*********************

内存管理:针对的是实例的内存占用的管理(放在堆里面)

实例:1:由class类型构建的实例,2:闭包对象

内存管理技术:ARC:Automatic Reference Count

自动:由语言本身帮我们销毁内存,不需要你手动销毁,

比如在c中就调用dealloc()

引用:let p = Person()  p就是对Person()这个对象的一个引用

计数: let p = Person() //一个

/ / let pp = p   //二个

利用析构函数来判断是否销毁

class Person {
    var name: String
    init(name: String ) {
        self.name = name
    }
    deinit {
        print("\(name) person deinit")
    }
}

var p: Person? = Person(name: "david")
//p = nil
var pp = p
p = nil
pp = Person(name: "banzhang")
pp = nil

引用增加:一般是把一个对象不断的赋值给变得变量或属性等

引用减少:手动把变量等得值赋值为nil活着让其引用一个新的对象,活着函数执行完毕(比如下面)


class Person {
    var name: String
    init(name: String ) {
        self.name = name
    }
    deinit {
        print("\(name) person deinit")
    }   }

func testArc() {
     var p = Person(name: "chenhe")
     print(p.name)
}

testArc() //系统自动调用deinit

*************循环引用*************

循环引用的阐述

class Student {
    var name: String
    var t: Teacher?
    init(name: String) {
        self.name = name
    }
    deinit {
        print("\(name) student deinit")
    }
}

class Teacher {
    var name: String
    var banzhang: Student?
    init(name: String) {
        self.name = name
    }
    deinit {
        print("\(name) teacher deinit")
    }
}
var teacher:Teacher? = Teacher(name: "cheng")
var bc:Student? = Student(name: "ling")
teacher?.banzhang  = bc
bc?.t = teacher

teacher = nil
bc?.t = nil
bc = nil  //因为是两个强引用,所以还要bc?,t=nil

//循环引用的解决办法:weak(弱引用)和unowned(非拥有)

循环引用:为了解决内存泄露与空悬指针的问题

解决空悬指针的办法只有两种:一种是把其值赋值为nil,另一种是把其指向另外的新对象(这种方法不可行)

在swift中,赋值为nil只有用?或!声明的类成员才行

严格来说,就只有3种情况需要考虑

**********第一种情况:两边都是?

class Student {
    var name: String
    var t: Teacher?
    init(name: String) {
        self.name = name
    }
    deinit {
        print("\(name) student deinit")
    }
}

class Teacher {
    var name: String
    weak var banzhang: Student?
    init(name: String) {
        self.name = name
    }
    deinit {
        print("\(name) teacher deinit")
    }
}
var teacher:Teacher? = Teacher(name: "cj")
var bc:Student? = Student(name: "yeweidong")
teacher?.banzhang  = bc
bc?.t = teacher

bc = nil
teacher = nil //因为teacher是weak

第二种情况:一边为可空类型,一边为非可空类型(unowned)

class Student2 {
    var name: String
    var t: Teacher2?
    init(name: String) {
        self.name = name
    }
    deinit {
        print("\(name) student deinit")
    }
}

class Teacher2 {
    var name: String
    //unowned修饰在非可选类型上,不能用weak,weak只能用在可选类型
    unowned var banzhang: Student2
    init(name: String,stu: Student2) {
        self.name = name
        self.banzhang = stu
    }
    deinit {
        print("\(name) teacher deinit")
    }
}
var s1: Student2? = Student2(name: "ch")
var teac: Teacher2? = Teacher2(name: "david", stu: s1!)
s1?.t = teac
teac?.banzhang = s1!

s1 = nil 

第三种情况

//第三种情况:两边都是非可空类型

class Student3 {
    var name: String
    var t: Teacher3!  //nil
    init(name: String,teacherName: String) {

        self.name = name//这行代码运行后name有值,然后t有nil,所以self就可以用
        self.t = Teacher3(name: teacherName, stu: self)
    }
    deinit {
        print("\(name) student deinit")
    }
}

class Teacher3 {
    var name: String

    //     var banzhang: Student3 = Student3(name: "xuesheng", teacher: self)//不能用self,除非lazy
    unowned var banzhang: Student3
    init(name: String,stu: Student3) {
        self.name = name
        self.banzhang = stu
    }
    deinit {
        print("\(name) teacher deinit")
    }
}

//如果两个类中,其属性都是非可空类型,并且互相引用

//那么会导致这两个对象永远不能创建出来

var s3: Student3? = Student3(name: "xxx", teacherName: "zhuzhu")

var t3 = Teacher3(name: "zhuzhu", stu: s3!)

s3?.t = nil

s3 = nil



循环引用在闭包中的体现
class ClosureClass {
    var name = "asdf"
    //利用方括号语法(捕获列表)来处理循环引用
    //多个之间用逗号分隔
    lazy var myClosure:Void->Int = {
        //[unowned self] //直接修饰unowned或weak
        [unowned this = self]//除了修饰以外,还可以取别名
        //[unowned this = self,unowned self]
        ()-> Int in
        print(this.name)
        print(self.name)
        return 5
    }
    deinit {
        print("closer deinit")
    }
}
//有两个对象,一个是ClosureClass对象,一个是闭包对象
var cc: ClosureClass? = ClosureClass()
cc?.myClosure()
cc = nil
cc?.myClosure()  //输出nil,说明已被销毁
时间: 2024-10-25 11:55:12

内存管理:内存泄漏和空悬指针的相关文章

内存是手游的硬伤——Unity游戏Mono内存管理与泄漏

WeTest导读 内存是游戏的硬伤,如果没有做好内存的管理问题,游戏极有可能会出现卡顿,闪退等影响用户体验的现象.本文介绍了在腾讯游戏在Unity游戏开发过程中常见的Mono内存管理问题,并介绍了一系列解决的策略和方法. 内存是手游的硬伤 无论是游戏还是VR应用,内存管理都是其研发阶段的重中之重.然而,90%以上的项目都存在不同程度的内存使用问题.就目前基于Unity引擎开发的移动游戏和移动VR游戏而言,内存的开销无外乎以下三大部分: 1.资源内存占用: 2.引擎模块自身内存占用: 3.托管堆内

空悬指针和野指针

前言 以前经常把这两个概念混为一谈,虽然这它们的概念类似,有一定的相似性,但是各自的成因和解决防范方法都是不同的,特记录在此. 空悬指针 定义 一个原生指针分配内存后,它并没有探测内存是否已经被释放或者被损坏的能力.当所管理的内存被释放后,若这个指针没有被销毁或置为NULL,它就成了一个空悬指针. 危害 可能会出现随机的错误,甚至导致程序崩溃,而且这种问题一般很难定位,特别是在大型工程里. 解决方法 使用weak_ptr和shared_ptr配套可以解决"不知道对象是否还活着"的问题.

空悬指针和野指针(Dangling pointer and wild pointer)

空悬指针 简单地说,空悬指针是对象的指针的生存周期比对象更长所导致的,也就是说,对象销毁.删除了,不存在了,指针仍然存在,这时这个指针就成了空悬指针. 当对象被析构.删除时,如果指向它的指针没有被同时修改,那么指针仍然会指向那块内存(但是那块内存已经没有东西了).系统此时可能会重新分配这块已经free掉的内存,如果程序再通过这个指针读这块内存,就可能会有不可预见的事情发生,因为这块内存可能被分配了完全不同的内容.如果程序此时要写这块内存,就可能会造成数据污染,进而可能带来超级难被发现的bug.如

计算机操作系统学习笔记_7_内存管理 --内存管理基础

h2.western { font-family: "Liberation Sans",sans-serif; font-size: 16pt; }h2.cjk { font-family: "微软雅黑"; font-size: 16pt; }h2.ctl { font-family: "AR PL UMing CN"; font-size: 16pt; }h1 { margin-bottom: 0.21cm; }h1.western { fon

Objective-C(十六、内存管理,自动释放池,ARC,强指针,弱指针,方法族)——iOS开发基础

结合之前的学习笔记以及参考<Objective-C编程全解(第三版)>,对Objective-C知识点进行梳理总结.知识点一直在变,只是作为参考,以苹果官方文档为准~ 十六.内存管理相关知识(二) 1.autorelease,自动释放机制 - (instancetype)autorelease; (1)自动释放池的创建 iOS5.0之前 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; //进行一系列操作 //此处不可以使用

内存管理 &amp; 内存优化技巧 浅析

内存管理 浅析 下列行为都会增加一个app的内存占用: 1.创建一个OC对象: 2.定义一个变量: 3.调用一个函数或者方法. 如果app占用内存过大,系统可能会强制关闭app,造成闪退现象,影响用户体验.如何让回收那些不再使用的对象呢?本文着重介绍OC中的内存管理. 所谓内存管理,就是对内存进行管理,涉及的操作有: 1.分配内存:比如创建一个对象,会增加内存占用: 2.清除内存:比如销毁一个对象,会减少内存占用. 内存管理的管理范围: 1.任何继承了NSObject的对象: 2.对其他非对象类

内存管理 浅析 内存管理/内存优化技巧

内存管理 浅析 下列行为都会增加一个app的内存占用: 1.创建一个OC对象: 2.定义一个变量: 3.调用一个函数或者方法. 如果app占用内存过大,系统可能会强制关闭app,造成闪退现象,影响用户体验.如何让回收那些不再使用的对象呢?本文着重介绍OC中的内存管理. 所谓内存管理,就是对内存进行管理,涉及的操作有: 1.分配内存:比如创建一个对象,会增加内存占用: 2.清除内存:比如销毁一个对象,会减少内存占用. 内存管理的管理范围: 1.任何继承了NSObject的对象: 2.对其他非对象类

深入理解_JVM内存管理内存分配和回收策略06

解决两个问题: 1.对象分配内存: 2.回收分配给对象的内存. 本节详细讲解分配的问题: 名词解释: 新生代GC(Minor GC):指发生在新生代的垃圾回收动作,非常频繁,回收速度很快. 老生代GC(Major GC/Full GC):指发生在老生代的垃圾回收动作,出现了Major GC,经常会伴随至少一次的Minor GC(但非绝对),速度一般会比Minor GC慢10倍. 打印日志说明: <1> DefNew:串行GC方式(Serial GC). <2> ParNew:Par

内存管理---内存释放

Linux内存释放函数之间的调用关系如下图所示 hi /*用虚拟地址进行释放*/ void free_pages(unsigned long addr, unsigned int order) { if (addr != 0) { VM_BUG_ON(!virt_addr_valid((void *)addr)); __free_pages(virt_to_page((void *)addr), order);/*具体的释放函数*/ } } void __free_pages(struct pa