首页 > 解决方案 > 使用 UnsafeMutablePointer 访问释放的内存

问题描述

我对UnsafeMutablePointer.

以下代码按预期崩溃,因为我们试图访问已经被释放的内存。

let storage = UnsafeMutablePointer<[UInt8]>.allocate(capacity: 1)
// initialize
storage.initialize(to: [0x01])

storage.deinitialize(count: 1)
storage.deallocate()

print(storage) // 0x00007ff236404890
print(storage.pointee) // Will Crash EXC_BAD_ACCESS 

将类型更改为 Bool 不会使应用程序崩溃,我们可以读取指针值。为什么会这样?

let storage = UnsafeMutablePointer<Bool>.allocate(capacity: 1)
// initialize
storage.initialize(to: false)

storage.deinitialize(count: 1)
storage.deallocate()

print(storage) // 0x00007ff236404890
print(storage.pointee) // false

标签: iosswift

解决方案


@jckarter 在 Twitter 上为我回答了这个问题。

因此,首先在直接使用内存时使用地址清理器总是好的。

在释放内存后访问内存是未定义的行为。因此,可能会发生多种事情,我们不能依赖于此。

这种行为是因为:

当您释放内存时,它不一定会立即返回到操作系统,因为在需要新分配之前将内存保持原样会更有效。因此,您可能可以在内存释放后的某个时间访问旧值,但您不能依赖它。

使用诸如 Address Sanitizer 或 Guard Malloc 之类的内存检查工具应该使行为更可预测,因为它们增加了对释放后使用的内存的更多检查

--@jckarter

启用地址清理程序时的说明:

let storage = UnsafeMutablePointer<Bool>.allocate(capacity: 1)
// initialize
storage.initialize(to: false)

storage.deinitialize(count: 1)
storage.deallocate()

print(storage) 
print(storage.pointee) // Thread 1: Use of deallocated memory ❗️

推荐阅读