Swift在什么情况会发生内存访问冲突详解_Swift

来源:脚本之家  责任编辑:小易  

前言

众所周知,Swift 是一门类型安全的语言,它会通过编译器报错来阻止你代码中不安全的行为。比如变量必须在使用之前声明、变量被销毁之后内存不能在访问、数组越界等问题。

Swift 会通过对于修改同一块内存,同一时间以互斥访问权限的方式(同一时间,只能有一个写权限),来确保你的代码不会发生内存访问冲突。虽然 Swift 是自动管理内存的,在大多数情况下你并不需要关心这个。但理解何种情况下会发生内存访问冲突也是十分必要的。

首先,来看一下什么是内存访问冲突。

内存访问冲突

当你设值或者读取变量的值得时候,就会访问内存。

var age = 10 // 写权限
print(age) // 读权限

当我们对同一块内存,同时进行读写操作时,会产生不可预知的错误。比如上面的 age,假如在你读取它值的期间有别的代码将它设为 20,那么你读取到的有可能是 10,也有可能是 20。这就产生了问题。

内存访问冲突:对同一块内存,同时进行读写操作,或者同时进行多个写入操作时,就会造成内存访问冲突。

了解了什么是内存访问冲突,下面来看下什么情况下回造成内存访问冲突。

In-Out 参数

当 In-Out 参数为全局变量,并且该变量在函数体内被修改时,就会造成内存访问冲突。比如下面的代码:

var age = 10

func increment(_ num: inout Int) { // step1
 num += age // step2
}
increment(&age)

increment(:) 在整个函数体内,对所有的 In-Out 参数都有写权限。在上述代码中,step1 已经获得了 age 的写权限,而 step2 有得到了 age 的读权限,这样就造成了同一块内存,同时进行了读写操作。从而造成了内存访问冲突。

上面的问题可以通过将 age 拷贝一份来解决:

// step1
var copyOfAge = age
increment(&copyOfAge)
age = copyOfAge

step1 将 age 的值拷贝到另一块内存上,这样在函数体内就是存在对 age 的读权限和对 copyOfAge 的写权限,因为 age 和 copyOfAge 是两块内存,所以就不会造成内存访问冲突。

结构体的 mutating 函数

对于结构体的 mutating 函数来说,它整个函数体都有 self 的写权限。

struct Person {
 var age: Int
 mutating func increment(_ num: inout Int) { 
  age += num 
 }
}

var p1 = Person(age: 10)
p1.increment(&p1.age)

上述的代码编译器会报错:Overlapping accesses to 'p1', but modification requires exclusive access; consider copying to a local variable。很明显这是一个内存访问冲突。

In-Out 参数获得了 p1 的写权限;mutating 函数也获得了 p1 的写权限。同一块内存,同时有两个写操作。造成内存访问冲突。可以通过同上的拷贝操作来解决。

值类型的属性

对于结构体、枚举、元祖等值类型来说,修改它们的属性就相当于修改它们整个的值。比如下面的代码:

func increment(_ num1: inout Int, _ num2: inout Int) {
 print(num1 + num2)
}

var tuple = (age: 10, height: 20)
increment(&tuple.age, &tuple.height)

&tuple.age 拿到了 tuple 的写权限,&tuple.height 又拿了 tuple 的写权限。同一块内存,同时有两个写操作。造成内存访问冲突。

这个问题可以通过局部变量来解决:

func someFunction() {
 var tuple = (age: 10, height: 20)
 increment(&tuple.age, &tuple.height)
}

因为在 someFunction() 函数里,age 和 height 没有产生任何的交互(没有在其期间去读取或者写入 age 和 height),所以编译器可以保证内存安全。

PS:关于评论区的问题,在 someFunction() 函数里没有任何交互是什么意思?

答:在someFunction() 里,编译器可以保证没有别的线程来读取或者修改 tuple。因此,可以保证内存安全。而对于全局变量,编译器无法保证是否有别的线程在读取或者修改。

下面的代码就是在函数体内有交互的代码,虽然是局部变量,但涉及多个线程修改 tuple 的值,因此会造成内存访问冲突:

func someFunction() {
 var tuple = (age: 10, height: 20)
 
 DispatchQueue.main.async {
  tuple.age += 10
 }
 
 DispatchQueue.main.async {
  increment(&tuple.age, &tuple.height)
 }
}

总结

对同一块内存,同时进行读写操作,或者同时进行多个写入操作时,就会造成内存访问冲突。

会造成内存访问冲突的情况:

In-Out 为全局参数,并且在函数体内修改了它。 结构体的 mutating 函数内修改结构体的值。 同一值类型的多个属性当做函数的 In-Out 参数。

到此这篇关于Swift在什么情况会发生内存访问冲突的文章就介绍到这了,更多相关Swift内存访问冲突内容请搜索真格学网以前的文章或继续浏览下面的相关文章希望大家以后多多支持真格学网!

您可能感兴趣的文章:深入讲解Swift的内存管理Swift编程中用以管理内存的自动引用计数详解详谈swift内存管理中的引用计数详解 swift3.0 可选绑定共用同一块内存空间的实例

  • 本文相关:
  • swift如何调用objective-c的可变参数函数详解
  • 10个惊艳的swift单行代码
  • swift让输入框跟随键盘弹起避免输入输入法挡住输入框问题
  • swift的函数式编程详解
  • swift3.0指纹解锁的实现方法
  • 在swift中使用objective-c编写类、继承objective-c类
  • swift实现文件压缩和解压示例代码
  • swift计步器cmpedometer的使用方法
  • 举例讲解swift编程中switch...case语句的用法
  • swiftui使用paths和animatabledata实现酷炫的颜色切换动画
  • swift什么情况下可以使用闭包
  • 在swift下,这样写为什么不会引起循环引用?
  • swift 什么情况下使用闭包
  • 内存访问冲突
  • 发生访问冲突
  • Swift中import两个模块,好像有冲突,同时用就报错...
  • UG4.0在编程的时候出现内存访问冲突是什么原因
  • 写入位置 0xCDCDCDCD 时发生访问冲突,这个错误是...
  • 这个程序为什么会出现读取位置时发生访问冲突?
  • 电脑有时会出现”内存访问冲突“的问题,是不是电脑...
  • 网站首页网页制作脚本下载服务器操作系统网站运营平面设计媒体动画电脑基础硬件教程网络安全c#教程vbvb.netc 语言java编程delphijavaandroidiosswiftscala易语言汇编语言其它相关首页深入讲解swift的内存管理swift编程中用以管理内存的自动引用计数详解详谈swift内存管理中的引用计数详解 swift3.0 可选绑定共用同一块内存空间的实例swift如何调用objective-c的可变参数函数详解10个惊艳的swift单行代码swift让输入框跟随键盘弹起避免输入输入法挡住输入框问题swift的函数式编程详解swift3.0指纹解锁的实现方法在swift中使用objective-c编写类、继承objective-c类swift实现文件压缩和解压示例代码swift计步器cmpedometer的使用方法举例讲解swift编程中switch...case语句的用法swiftui使用paths和animatabledata实现酷炫的颜色切换动画mac git xcrun error active dev在一个项目中同时使用swift和objswift4.0 array数组详解利用swift如何判断iphone x机型详swift的74个常用内置函数介绍升级到swift 4.0可能遇到的坑总结swift之uitabbarcontroller 导航swift中动态调用实例方法介绍swift在控件中添加点击手势的方法详解swift中enum枚举类型的用法swift与objective c的简单对比swift教程之类的析构详解swift心得笔记之函数switch实现一个两数的运算代码示例实例讲解swift中引用类型的arc自动引用计swift算法之二叉树实现的方法示例swift实现快速排序算法的代码示例swift中使用可选类型完美解决占位问题如何快速用上swift静态库详解swift解决uitableview空数据视图问题的简
    免责声明 - 关于我们 - 联系我们 - 广告联系 - 友情链接 - 帮助中心 - 频道导航
    Copyright © 2017 www.zgxue.com All Rights Reserved