提问人:Yanni 提问时间:12/31/2020 最后编辑:Yanni 更新时间:1/3/2021 访问量:129
在 32 位 iOS 设备中,快速闭包中的 BOOL 签名是错误的
The signature of BOOL in a swift closure is wrong in a 32-bit iOS device
问:
BOOL 的签名通常在 objective-c, Reference 中是“B”。
但在 32 位设备上。BOOL 的签名是“c”。参考
有趣的发现
有趣的是,在 32 位设备上,快速闭包中的 BOOL 是“B”(应该是“c”)。
例如,这是一个快速关闭。
let closure = {_ in
} as @convention(block) (Bool) -> Void
在 32 位设备上,闭包的签名是 v8@?0B4。按理说,它应该是 v8@?0c4。
如何验证?
sh_blockSignature
(C 代码)是从块中获取签名的函数
测试.m
enum {
// Set to true on blocks that have captures (and thus are not true
// global blocks) but are known not to escape for various other
// reasons. For backward compatibility with old runtimes, whenever
// BLOCK_IS_NOESCAPE is set, BLOCK_IS_GLOBAL is set too. Copying a
// non-escaping block returns the original block and releasing such a
// block is a no-op, which is exactly how global blocks are handled.
BLOCK_IS_NOESCAPE = (1 << 23),
BLOCK_HAS_COPY_DISPOSE = (1 << 25),
BLOCK_HAS_CTOR = (1 << 26), // helpers have C++ code
BLOCK_IS_GLOBAL = (1 << 28),
BLOCK_HAS_STRET = (1 << 29), // IFF BLOCK_HAS_SIGNATURE
BLOCK_HAS_SIGNATURE = (1 << 30),
};
struct Block_literal_1 {
void *isa; // initialized to &_NSConcreteStackBlock or &_NSConcreteGlobalBlock
int flags;
int reserved;
void (*invoke)(void *, ...);
struct Block_descriptor_1 {
unsigned long int reserved; // NULL
unsigned long int size; // sizeof(struct Block_literal_1)
// optional helper functions
void (*copy_helper)(void *dst, void *src); // IFF (1<<25)
void (*dispose_helper)(void *src); // IFF (1<<25)
// required ABI.2010.3.16
const char *signature; // IFF (1<<30)
} *descriptor;
// imported variables
};
const char * _Nullable sh_blockSignature(id block)
{
struct Block_literal_1 *layout = (__bridge void *)block;
if (!(layout->flags & BLOCK_HAS_SIGNATURE))
return nil;
void *descRef = layout->descriptor;
descRef += 2 * sizeof(unsigned long int);
if (layout->flags & BLOCK_HAS_COPY_DISPOSE)
descRef += 2 * sizeof(void *);
if (!descRef) return nil;
const char *signature = (*(const char **)descRef);
return signature;
}
测试2.swift
let closure = {_ in
} as @convention(block) (Bool) -> Void
let p = sh_blockSignature(closure)!
let signature = String.init(cString: p)
print(signature) // "v8@?0B4"
这是 32 位设备上的快速错误吗?
答: 暂无答案
评论
c
B