block 的内存结构衍生出来的面试题
今天在群里看到大佬们在讨论一个面试题,问如下代码在 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 在内存中的数据结构。
- 注释②是一个函数调用语句,可以简化成:
((__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
结论:
- 答案:在 32bit 系统中报错:
EXC_BAD_ACCESS(address = 0x0C),在 64bit 系统中报错EXC_BAD_ACCESS(address = 0x10) - block 本质是一个结构体,在探究 block 相关的问题时,转换成
C++代码后往往就可以一目了然,比如weakSelf 为什么可以解决循环引用
- 答案:在 32bit 系统中报错:
block 的内存结构衍生出来的面试题的更多相关文章
- 从汇编代码理解 Block 的内存结构
❓ 在断点调试 iOS 程序碰到 block 作为函数的形参时,如果想知道该 block 本身的函数签名信息和函数体地址时,有哪些办法?
- block本质探寻一之内存结构
一.代码——命令行模式 //main.m #import <Foundation/Foundation.h> struct __block_impl { void *isa; int Fl ...
- Oracle之内存结构(SGA、PGA)
一.内存结构 SGA(System Global Area):由所有服务进程和后台进程共享: PGA(Program Global Area):由每个服务进程.后台进程专有:每个进程都有一个PGA. ...
- [转]oracle学习入门系列之五内存结构、数据库结构、进程
原文地址:http://www.2cto.com/database/201505/399285.html 1 Oracle数据库结构 关于这个话题,网上一搜绝对一大把,更别提书籍上出现的了,还有很多大 ...
- Java内存结构、类的初始化、及对象构造过程
概述 网上关于该题目的文章已经很多,我觉得把它们几个关联起来讲可能更好理解一下.与其它语言一样,它在执行我们写的程序前要先分配内存空间,以便于存放代码.数据:程序的执行过程其实依然是代码的执行及数据的 ...
- [转载] Oracle之内存结构(SGA、PGA)
2011-05-10 14:57:53 分类: Linux 一.内存结构 SGA(System Global Area):由所有服务进程和后台进程共享: PGA(Program Global Area ...
- JVM内存结构之堆、栈、方法区以及直接内存、堆和栈区别
JVM内存结构之堆.栈.方法区以及直接内存.堆和栈区别 一. 理解JVM中堆与栈以及方法区 堆(heap):FIFO(队列优先,先进先出):二级缓存:*JVM中只有一个堆区被所有线程所共享:对象和数 ...
- oracle内存结构
一.内存结构 SGA(System Global Area):由所有服务进程和后台进程共享: PGA(Program Global Area):由每个服务进程.后台进程专有:每个进程都有一个PGA. ...
- JAVA 对象内存结构
JAVA对象内存结构 HotSpot虚拟机中,对象在内存中存储的布局可以分为三块区域:对象头(Header).实例数据(Instance Data)和对齐填充(Padding). 对象头 markWo ...
随机推荐
- 使用NPOI将Excel表导入到数据库中
public string ExcelFile() { //指定文件路径, string fileName=@"d:\Stu.xls"; //创建一个文件流,并指定其中属性 usi ...
- 日常破解---XCTF_APP1获取flag记录
日常破解---XCTF_APP1获取flag记录 一.题目来源 来源:XCTF社区安卓题目app1 二.解题记录 1.首先安装到模拟器中运行一下,如下图所示,点击一下按钮,弹出提示年轻人不 ...
- Linux基本操作及常用指令
今天复习了下Linux的基本操作及常用指令,上学期大数据云计算课一直也在用linux系统还是比较熟悉的,并在centos6.7虚拟机上部署了前几天做的web项目,了解了Nginx的反向代理与负载均衡, ...
- [poj1062][最短路]昂贵的聘礼
(最近总是有想让我的小博客更加充实的冲动,遇见一个不平常的题就想写下来.今天这个题姑且算是同学推荐的好题,很有意思,志之) 题目 题面 年轻的探险家来到了一个印第安部落里.在那里他和酋长的女儿相爱了, ...
- linux 读取 USB HID鼠标坐标和点击 在 LCD上显示
首先要,编译内核时启用了 USB HID 设备.启用了 鼠标 . 在开发板上插入usb 时会有如下提示. 可以看到,多了一个 mouse0 和 eventX 打出来的是我的 联想鼠标. 1, 在 终端 ...
- 我的学习笔记之node----node.js+socket.io实时聊天(1)
本想着从hello word开篇,也确实写了相关学习笔记.各种原因吧,现在又着急写出作品,便作罢. 这里将记录一个node.js+socket.io的实时聊天程序.(当然我也是跟着网上各种教程资料学习 ...
- touch事件中的touches、targetTouches和changedTouches
touches: 当前屏幕上所有触摸点的列表; targetTouches: 当前对象上所有触摸点的列表; changedTouches: 涉及当前(引发)事件的触摸点的列表; 通过一个例子来区分一下 ...
- (转)协议森林11 涅槃 (TCP重新发送)
协议森林11 涅槃 (TCP重新发送) 作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! TCP协议是一个可靠的协议.它通过重新发送 ...
- 记一次在新服务器上搭建lnmp的过程
背景: 前不久阿里云在做活动,200+一台服务器三年,于是果断入手了一台. 今天有空就在服务器上把lnmp环境给装了,之前为了了解安装过程,在别的机器上尝试过单独安装nginx.mysql.php,虽 ...
- Javaweb编程
首先是题目要求: 1登录账号:要求由6到12位字母.数字.下划线组成,只有字母可以开头:(1分) 2登录密码:要求显示“• ”或“*”表示输入位数,密码要求八位以上字母.数字组成.(1分) 3性别:要 ...