指针
1、指针不安全
- 指针是不安全的,
- 越界
- 类型不同
2、指针类型
typed pointer
指定类型指针raw pointer
未指定类型指针(原生指针)
Swift | oc | 说明 |
---|---|---|
unsafePointer <T> | const T* | 指针及指向的内容都不可变 |
unsafeMutablePointer<T> | T* | 指针及其指向内存内容都可变 |
unsafeRawPointer | const void* | 指针指向的内存区域未定 |
unsafeMutableRawPointer | void* | 同上 |
unsafeBufferPointer<T> | ||
unsafeMutableBufferPointer<T> | ||
unsafeRawBufferPointer | ||
unsafeMUtableRawBufferPointer |
3、原始指针的使用
print(MemoryLayout<GoodGame>.stride) /// 分配的内存大小
print(MemoryLayout<GoodGame>.alignment) /// 对齐
let size = MemoryLayout<GoodGame>.size
let stride = MemoryLayout<GoodGame>.stride
let alignment = MemoryLayout<GoodGame>.alignment
let p = UnsafeMutableRawPointer.allocate(byteCount: 4 * stride, alignment: alignment)
for i in 0..<4 {
p.advanced(by: i * stride).storeBytes(of: i*i, as: Int.self)
}
for i in 0..<4 {
let value = p.load(fromByteOffset: i * stride, as: Int.self)
print("\(i)===\(value)")
}
p.deallocate() /// 清除
4、泛型指针
var age = 20
/// 获取当前变量的地址
withUnsafePointer(to: &age) { ptr in
print(ptr.pointee + 20)
}
/// withUnsafeMutablePointer
/// 访问
age = withUnsafePointer(to: &age) { ptr in
return ptr.pointee + 20
}
/// 直接分配内存 分配一块int类型内存空间。
let tPtr = UnsafeMutablePointer<Int>.allocate(capacity: 3)
/// 初始化
tPtr[0] = 2
tPtr[1] = 12
tPtr.initialize(to: age)
/// 访问内存的值
print(tPtr.pointee)
let a = tPtr.pointee + 20
/// Deinitializes the specified number of values starting at this pointer.
/// The region of memory starting at this pointer and covering `count`
/// instances of the pointer's `Pointee` type must be initialized. After
/// calling `deinitialize(count:)`, the memory is uninitialized, but still bound to the `Pointee` type.
/// - Parameter count: The number of instances to deinitialize. `count` must not be negative.
/// - Returns: A raw pointer to the same address as this pointer. The memory
/// referenced by the returned raw pointer is still bound to `Pointee`.
tPtr.deinitialize(count: 5)
tPtr.deallocate()
\
let kp = UnsafeMutablePointer<kosdfp>.allocate(capacity: 2)
kp.initialize(to: kosdfp())
kp.advanced(by: MemoryLayout<GoodGame>.stride).initialize(to: kosdfp(good1: true, good4: 20))
kp.deinitialize(count: 2)
kp.deallocate()
allocate
开辟 initialize
初始值 deinitialize
清零 deallocate
回收。有创建就要赋值,用完清零,再回收。
- 解析
macho
var size: UInt = 0
var ptr = getsectdata("__TEXT", "__swift5_types", &size)
var mhHeader = _dyld_get_image_header(0)
var setCommondPtr = getsegbyname("__LINKEDIT") /// 虚拟地址等信息
var linkBaseAdress: UInt64 = 0
/// 虚拟内存地址 - fileoff = 链接或者加载的基地址
if let vmaddr = setCommondPtr?.pointee.vmaddr, let fileoff = setCommondPtr?.pointee.fileoff {
linkBaseAdress = vmaddr - fileoff
}
var offset: UInt64 = 0
if let unwrapperPtr = ptr {
let intRepresentaion = UInt64(bitPattern: Int64(Int(bitPattern: unwrapperPtr)))
offset = intRepresentaion - linkBaseAdress
print(offset) /// 基地址
}
let mhHeaderPtr_IntReprensentation = UInt64(bitPattern: Int64(Int(bitPattern: mhHeader)))
/// 首地址 + offset = 程序运行存放真是内存地址
var dataLoAdress = mhHeaderPtr_IntReprensentation + offset
// 程序运行存放真是内存地址 指向4字节内容 先转换为指针类型
var dataLoAdressPtr = withUnsafePointer(to: &dataLoAdress) { return $0 }
// 通过指针类型返回 __swift5_types 中data Lo
var dataLoContent = UnsafePointer<UInt32>.init(bitPattern: Int(exactly: dataLoAdress) ?? 0)?.pointee
// 找到描述信息
//typeDescOffset 描述在macho 偏移信息
let typeDescOffset = UInt64(dataLoContent!) + offset - linkBaseAdress
//描述在macho偏移信息 加 首地址
var typeDescAdress = typeDescOffset + mhHeaderPtr_IntReprensentation
/// datalo
// classDescriptor的指针
let classDescriptor = UnsafePointer<TargetClassDescriptor>.init(bitPattern: Int(exactly: typeDescAdress) ?? 0)?.pointee
/// 获取name
if let name = classDescriptor?.name {
let nameOffset = Int64(name) + Int64(typeDescOffset) + 8
print(nameOffset)
let nameAdress = nameOffset + Int64(mhHeaderPtr_IntReprensentation)
print(nameAdress)
if let cChar = UnsafePointer<CChar>.init(bitPattern: Int(nameAdress)){
print(String(cString: cChar))
}
}
- 思路
类的属性
存放在TargetClassDescriptor
name
。描述文件中的name
- 需要得到
ClassDescriptor
的指针。ClassDescriptor
的指针是由运行首地址
+描述在macho偏移信息
中间进行指针偏移与转换。 运行首地址
var mhHeader = _dyld_get_image_header(0)
let mhHeaderPtr_IntReprensentation = UInt64(bitPattern: Int64(Int(bitPattern: mhHeader)))
描述在macho偏移信息
为__swift5_types
中的data lo +基地址
-链接或者加载的基地址
var setCommondPtr = getsegbyname("__LINKEDIT") /// 虚拟地址等信息
var linkBaseAdress: UInt64 = 0
/// 虚拟内存地址 - fileoff = 链接或者加载的基地址
if let vmaddr = setCommondPtr?.pointee.vmaddr, let fileoff = setCommondPtr?.pointee.fileoff {
linkBaseAdress = vmaddr - fileoff
}
var offset: UInt64 = 0
if let unwrapperPtr = ptr {
let intRepresentaion = UInt64(bitPattern: Int64(Int(bitPattern: unwrapperPtr)))
offset = intRepresentaion - linkBaseAdress
print(offset) /// 基地址
}
/// 首地址 + offset = 程序运行存放真是内存地址
var dataLoAdress = mhHeaderPtr_IntReprensentation + offset
// 程序运行存放真是内存地址 指向4字节内容 先转换为指针类型
var dataLoAdressPtr = withUnsafePointer(to: &dataLoAdress) { return $0 }
// 通过指针类型返回 __swift5_types 中data Lo
var dataLoContent = UnsafePointer<UInt32>.init(bitPattern: Int(exactly: dataLoAdress) ?? 0)?.pointee
// 找到描述信息
//typeDescOffset 描述在macho 偏移信息 - 链接或者加载的基地址
let typeDescOffset = UInt64(dataLoContent!) + offset - linkBaseAdress
//描述在macho偏移信息 加 首地址
var typeDescAdress = typeDescOffset + mhHeaderPtr_IntReprensentation
5、内存绑定
/// Unmanaged 用来获取对象内存指针
let objRawPtr = Unmanaged.passUnretained(t as AnyObject).toOpaque()
\
/// bind 类型为 HeapObject
let objPtr = objRawPtr.bindMemory(to: HeapObject.self, capacity: 1)
\
print(objPtr.pointee)
print("end")
\
let kt = kosdfpClass()
\
let opaquePointer = Unmanaged.passUnretained(kt as AnyObject).toOpaque()
\
let ttPtr = opaquePointer.bindMemory(to: HeapObject.self, capacity: MemoryLayout.stride(ofValue: kt))
指针绑定 重新绑定指针
assumingMemoryBound(to:)
bindingMempry(to: ,capacity: )
withMemoryRebound(to: ,capacity: ,body:)
内存管理
引用计数取决于 InlineRefCounts HeapObject中 InlineRefCounts refCounts -》 InlineRefCounts -》 RefCounts 模块类 初始化强引用 无主引用 位移,左移33位
size_t requiredSize,
size_t requiredAlignmentMask)
new (object) HeapObject(metadata);
// Initialize a HeapObject header as appropriate for a newly-allocated object.
constexpr HeapObject(HeapMetadata const *newMetadata)
: metadata(newMetadata)
, refCounts(InlineRefCounts::Initialized)
{ }
public:
enum Initialized_t { Initialized };
enum Immortal_t { Immortal };
\
// RefCounts must be trivially constructible to avoid ObjC++
// destruction overhead at runtime. Use RefCounts(Initialized)
// to produce an initialized instance.
RefCounts() = default;
// Refcount of a new object is 1.
constexpr RefCounts(Initialized_t)
: refCounts(RefCountBits(0, 1)) {}
SWIFT_ALWAYS_INLINE
constexpr
RefCountBitsT(uint32_t strongExtraCount, uint32_t unownedCount)
: bits((BitsType(strongExtraCount) << Offsets::StrongExtraRefCountShift) |
(BitsType(1) << Offsets::PureSwiftDeallocShift) |
(BitsType(unownedCount) << Offsets::UnownedRefCountShift))
{ }
(BitsType(strongExtraCount) << Offsets::StrongExtraRefCountShift)\
shiftAfterField(name) = (name##Shift + name##BitCount)
strongExtraCount = 0 << Offsets::StrongExtraRefCountShift shiftAfterField(IsDeiniting); |
0 + 1 + 31 + 1 | 33 0x21 0x0010 0001
1 << Offsets::PureSwiftDeallocShift) PureSwiftDeallocShift = 0; |
1 << 0 |
unownedCount = 1 << Offsets::UnownedRefCountShift)) shiftAfterField(PureSwiftDealloc);
1 << 0 + 1 0x01 0x0000 00001 0010 0011
- 循环引用 unowned weak弱引用 无主引用。 swift_weakinit
refcount
0 1
31 32 3262 63 isimmortal unownedRefCount isDeinitingMask StrongExtraRefCount useSlowRc
isa
InlineRefCounts {
atomic<InlineRefCountBits> {
strong RC + unowned RC + flags
OR
HeapObjectSideTableEntry*
}
}
}
HeapObjectSideTableEntry {
SideTableRefCounts {
object pointer
atomic<SideTableRefCountBits> {
strong RC + unowned RC + weak RC + flags
}
}
}