标签:test http -objc 做了 命令行编译 ESS 面试题 sel res
今天在群里看到大佬们在讨论一个面试题,问如下代码在 32bit 和 64bit 系统上分别报什么错误:
#import <Foundation/Foundation.h>
int main()
{
void (^block)(void) = nil;
block();
return 0;
}
虽然有大佬一下子说出了答案,但我仍然一脸懵逼,后来经人提醒,这个考察 block 在内存中的结构,于是赶紧做了如下实验终于弄懂了为什么。
block_test.m
,在命令行编译成 C++:clang -rewrite-objc -fobjc-arc block_test.m
,打开同一目录下生成的block_test.cpp
文件,截取如下关键代码:// 注释①
struct __block_impl {
void *isa;
int Flags;
int Reserved;
void *FuncPtr;
};
int main()
{
void (*block)(void) = __null;
// 注释 ②
((void (*)(__block_impl *))((__block_impl *)block)->FuncPtr)((__block_impl *)block);
return 0;
}
解释:
((__block_impl *)block)->FuncPtr(block)
,即调用 __block_impl
类型指针指向的结构体中 FuncPtr
指向的函数,由于该结构体指针指向的内容为 null,因此 FuncPtr
指向的位置显然不是一个函数,所以该指针指向的位置会发生一个EXC_BAD_ACCESS
错误。FuncPtr
指向的位置是多少呢?根据上述__block_impl
中各成员变量的排列可知 FuncPtr
的偏移是 sizeof(void *) + sizeof(int) + sizeof(int)
,另外还需要考虑结构体内存对齐,参考这个链接,所以在 32bit 系统中,偏移:4 + 4 + 4 = 0x0C
;64bit 系统中,偏移:8 + 8 = 0x10
结论:
EXC_BAD_ACCESS(address = 0x0C)
,在 64bit 系统中报错EXC_BAD_ACCESS(address = 0x10)
C++
代码后往往就可以一目了然,比如weakSelf 为什么可以解决循环引用标签:test http -objc 做了 命令行编译 ESS 面试题 sel res
原文地址:https://www.cnblogs.com/boch2436/p/12660809.html