dispatch_async 是否复制内部块

2023-11-24

鉴于以下情况(手动引用计数):

void (^block)(void) = ^ {
    NSLog(@"wuttup");
}

void (^async_block)(void) = ^ {
    block();
}

dispatch_async(dispatch_get_main_queue(), async_block);

“块”会被复制而不是从堆栈中抛出并销毁吗?


我相信,答案是肯定的。

外部块将被异步分派,这会导致运行时在堆上为此块创建一个副本。如下所示,并在块实现规范 - Clang 3.4 文档,内部块的导入变量也被复制到堆中。

在OP的示例中,我们有一个“块引用的导入常量副本”。

我正在使用规范中的示例:

void (^existingBlock)(void) = ...;
void (^vv)(void) = ^{ existingBlock(); }
vv();

该规范指出copy_helper and dispose_helper需要函数:

copy_helper 函数会传递现有的基于堆栈的指针和指向新堆版本的指针,并且应该回调到运行时以实际对块内的导入字段执行复制操作。

规范中的以下示例代码很难破译(并且实际上缺少描述将外部块复制到堆时发生的情况)。无论如何,规范似乎试图表明内部块的导入变量将(递归地)复制到外部块的原始存储区域中。

当外部块将被复制到堆上时,内部块的导入变量似乎最终也会存在于堆上。

嗯,直觉上,这一切都是有道理的。

我做了一个小测试程序来证明这一点: (您必须调试并检查反汇编,才能弄清楚表面下发生了什么)。

#import <Foundation/Foundation.h>


void foo(int param)
{
    int x0 = param;
    int x1 = param + 1;
    void (^existingBlock)(void) = ^{
        int y0 = x0;
        int y1 = x1;
        printf("&y0: %p\n", &y0);
        printf("&y1: %p\n", &y1);
        printf("&x0: %p\n", &x0);
        printf("&x1: %p\n", &x1);
    };

    void (^vv)(void) = ^{
        int y2 = x0;
        int y3 = x1;
        existingBlock();
        printf("&y2: %p\n", &y2);
        printf("&y3: %p\n", &y3);
        printf("&x0: %p\n", &x0);
        printf("&x1: %p\n", &x1);
    };

    printf("Stack: &x: %p\n", &x0);
    printf("Stack: &x: %p\n", &x1);

    printf("------- on main thread -------\n");
    vv();

    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        printf("------- on thread 2 -------\n");
        assert(vv);
        sleep(1);
        int y4 = x0;
        int y5 = x1;
        vv();
        printf("&y4: %p\n", &y4);
        printf("&y5: %p\n", &y5);
        printf("&x0: %p\n", &x0);
        printf("&x1: %p\n", &x1);
    });
}

int main(int argc, const char * argv[])
{
    @autoreleasepool {

        foo(1);
        sleep(2);
    }
    return 0;
}

输出如下:

Stack: &x: 0x7fff5fbff868
Stack: &x: 0x7fff5fbff864
------- on main thread -------
&y0: 0x7fff5fbff70c
&y1: 0x7fff5fbff708
&x0: 0x1001081e0
&x1: 0x1001081e4
&y2: 0x7fff5fbff76c
&y3: 0x7fff5fbff768
&x0: 0x10010a588
&x1: 0x10010a58c
------- on thread 2 -------
&y0: 0x1000e5d9c
&y1: 0x1000e5d98
&x0: 0x1001081e0
&x1: 0x1001081e4
&y2: 0x1000e5dfc
&y3: 0x1000e5df8
&x0: 0x10010a588
&x1: 0x10010a58c
&y4: 0x1000e5e6c
&y5: 0x1000e5e68
&x0: 0x10010a5e8
&x1: 0x10010a5ec

当该块在主线程上执行时,它位于堆栈中(如本地变量和导入变量的地址所示)。当通过执行时dispatch_async运行时已复制该块 - 包括内部块,从块的本地变量和导入变量的地址可以看出。

我们可以在以下位置设置断点copy_helper_block函数,事实上,程序在那里停止一次,以便复制块vv到堆。

enter image description here

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

dispatch_async 是否复制内部块 的相关文章

  • 如何在 Objective-C 中创建可变参数方法

    也许这对你们大多数人来说显然很简单 但是您能否举例说明如何创建类似的方法 在 Objective C 中 和 C 中的函数来创建类似的函数NSString s stringWithFormat or NSLog 只是提醒一下 NSStrin
  • Objective-C 理解 isKindOfClass

    Objective C 和 XCode 的最新版本 4 4 我有一个代码片段 我无法理解为什么我能够使用某些行 让我解释一下 For understanding purpose NSMutableArray programStack id
  • 为什么在 Quick 单元测试中会多次调用 before- 和 afterEach 块?

    我编写了一个测试用例 其中包含一些示例组 包括beforeEach and afterEach 我期望每个beforeEach and afterEach每个都会被调用一次it 唉 对于一个人来说it the beforeEach and
  • 根据 UIView/CGRect 的大小将图像裁剪为正方形

    我有一个 AVCaptureSession 的实现 我的目标是让用户拍照并只保存红色方形边框内的图像部分 如下所示 AVCaptureSession 的previewLayer 相机 跨越 0 0 左上角 到相机控制栏的底部 包含快门的视图
  • 为 3D 模型的某些部分添加纹理

    我在实现 ARKit SceneKit 时遇到一个问题 我只想向 3D 模型的某些部分添加纹理 例如汽车的 3D 模型 我想更改车轮和镜子的纹理 let dragonScene SCNScene named art scnassets Dr
  • Cocoapods 和 Xcode,ld:找不到 -lAFNetworking 的库

    我有这个 pod 文件包含所有这些库 platform ios 7 0 target PP for iPad do pod AFNetworking 1 1 pod RaptureXML 1 0 pod NoticeView pod iVe
  • 存储应用内购买的正确且安全的方式

    在设备上存储应用内购买的最佳方式是什么 这样购买也可以离线访问 但是 购买的安全性没有受到损害 不要在设备上存储任何有价值的东西 因为它不可信 并且很容易被有动机的人破坏 现在 所有这一切都取决于所购买物品的类型和价值 以及如果物品受损会发
  • 获取请求,iOS

    我需要执行此 GET 请求 http api testmy co il api sync BID 1049 ClientCode 3847 Discount 2 34 Service 0 Items Name Tax Price 2 11
  • iOS 上的 Phonegap 3.5 媒体插件错误“无法使用 AvAudioRecorder 开始录音”

    我试图让用户在 Phonegap 应用程序中录制音频文件 它在 Android 上运行良好 但在 iOS 上 当开始录制时出现以下错误 无法使用 AvAudioRecorder 开始录音 我使用 wav 文件名 首先创建该文件 我已按照我找
  • 什么是 Core Audio 错误 561015905?为什么当我使用锁定按钮时会发生这种情况?

    自从升级到 iOS 10 和 Xcode 8 以来 每当我使用锁定按钮关闭屏幕时 我的 iOS 应用程序就会抛出错误并崩溃 错误是 由于未捕获的异常 com apple coreaudio avfaudio 而终止应用程序 原因 错误 56
  • SpriteKit中滚动背景的速度逐渐增加

    我正在 SpriteKit 中制作一个简单的游戏 并且我有一个滚动背景 简单的情况是 在加载游戏场景时 一些背景图像彼此相邻放置 然后当图像滚动到屏幕外时 图像会水平移动 这是我的游戏场景中的代码didMoveToView method s
  • 需要从另一个viewController调用其他viewController中的方法

    我有一个具有多个视图控制器的应用程序 其中一些视图控制器包含运行各种任务的方法 我需要做的是 当初始 viewController 加载时 在其他 viewController 中调用这些方法 以便它们在后台运行 但是 我在执行此操作时遇到
  • 当 Firebase 数据库中的值发生更改时创建推送通知

    我想在 firebase 数据库中的值发生更改时向用户发送推送通知 这是我的数据库 Battles 00000111 062B3333 4046 4FB4 AA37 C2B05853E497 BattleProgress Player1 l
  • 如何检索所有连接的蓝牙外围设备

    我正在尝试获取所有连接到 iPhone 的外围设备的列表 我已连接 Bose Soundlink 但它没有显示在我的应用程序中 我不知道 UUID 所以传递 因为这应该得到我想的一切 func centralManagerDidUpdate
  • 如何让 UIPickerView 滑动到屏幕的一半?

    when someone clicks clothing I want the UIPickerView to slide up as in the example as follows 有人可以展示代码示例吗 正如 dsc 和 Jason
  • 如何在构建时自动重置 iPhone 模拟器

    将多个 JSON 文件从应用程序包根目录移动到目录结构内 也在应用程序包中 后 应用程序继续运行 就像文件保留在之前的位置一样 经过一番绞尽脑汁并进行了一次干净的构建后 我记得必须清除 iPhone 模拟器才能删除旧位置中的这些文件 如果能
  • 编译到模拟器时如何排除 Xcode 中的框架

    我在我的项目中包含了 TokBox 框架 这样我们就可以进行视频短信 问题是该框架以及它们所需的其他一些框架不允许您在模拟器中编译或运行该应用程序 他们不受支持 有没有办法设置编译器标志以在编译到模拟器时跳过 TokBox 和其他框架 原因
  • Twitter iOS 个人资料页面配置

    我正在尝试构建一个类似于 Twitter 个人资料页面的页面 看起来他们正在使用基本的UITableView 最上面的配置文件就是tableHeaderView 这些选项卡是UISegmentedControl在SectionRowHead
  • 在滚动视图内的 ImageView 中裁剪缩放图像

    我已经做了很多努力 最后我需要帮助 谢谢 目标 1 如何将 imageView 放入 ScrollView 中 2 我如何在scrollView内部裁剪缩放图像 我在滚动视图中有一个 imageView 我想要缩放后裁剪图像 该图像显示在滚
  • 为什么还调用 calloutAccessoryControlTapped 来点击注释视图?

    我的视图控制器上有一张地图 我不知道为什么 但委托calloutAccessoryControlTapped 当我点击注释视图时也会调用 而不仅仅是当我点击细节关闭时 那么为什么会有这种行为呢 import UIKit import Map

随机推荐

  • JPA 在 MySQLIntegrityConstraintViolationException 中插入父/子结果

    这个问题已经被问过很多次了 但我没有找到任何好的答案 所以我会再问一次 我的父子单向关系如下 Entity Table name PARENT public class Parent Id GeneratedValue strategy G
  • WPF:MessageBox 是否会破坏 PreviewMouseDown?

    我一直在尝试让我的 WPF 应用程序提示用户在使用 TreeView 导航时放弃未保存的更改或取消 如何取消用户的 WPF 树视图点击 我如何 正确处理 PreviewMouseDown 带有消息框的事件 确认 我想我发现了一个错误 Mes
  • PDO 和 LOAD DATA LOCAL INFILE 不起作用

    我只是尝试将 LOAD DATA LOCL INFILE 与 pdo 一起使用 不适合我 这是我的功能 function connect db name db host db user db pass try this gt connect
  • 如何使用 Selenium(任何版本)下载图像?

    我想知道如何使用 selenium webdriver 下载页面的图像 假设需要用户会话来下载图像 因此纯 URL 没有帮助 任何示例代码都受到高度赞赏 我更喜欢做这样的事情 1 Get the SRC attribute of the i
  • FocusedElement 未得到尊重

    我使用 Prism 和 MVVM 创建了一个基本应用程序 到目前为止 它仅由 Shell 和一个 View ViewModel 组成 在应用程序加载期间 我将视图加载到我的主区域中 并将其显示在屏幕上 这可行 但我无法使视图上的文本框聚焦
  • 截取包含 iframe 的页面的屏幕截图

    我们有一个 NodeJS Angular 4 网站 它显示来自第三方 powerBI Emebdded 的 iframe 我们正在尝试开发一项功能 允许最终用户截取页面的屏幕截图 包括 iframe 的内容 我们尝试了 iframe2ima
  • 使用javascript无限定时器循环(没有setInterval)?

    我被 朋友 要求建立一个计时器 无限的 每秒写一行 但没有setInterval I solved它与 var i 0 function k myId cb setTimeout function console log myId cb 1
  • 有没有办法结合多个特征来定义一个新特征? [复制]

    这个问题在这里已经有答案了 有没有办法组合多个特征 通过继承 来定义一个新特征 我正在寻找类似 C 中的概念的东西 auto concept newConcept
  • 如何 SendMessage() 到另一个线程上创建的窗口?

    我有一个我想要的情况SendMessage到创建的窗口另一个线程比打电话的人SendMessage 默认行为似乎是永远阻塞并且不工作 所以我将呼叫更改为PostMessage 这不会阻塞发送线程 但消息似乎永远不会到达预期的窗口 那我该怎么
  • 如何向使用 autobuild 制作的 docker 镜像添加标签

    我四处搜寻 找不到真正的答案 如果我创建一个 docker git repo 并为我的 dockerhub 帐户设置自动构建 它将使用单个标签 即最新 或 1 0 或 foo 进行构建 但我找不到任何方法可以像通过命令那样添加标签与本地构建
  • IIS 应用程序在响应标头中缺少内容编码 - gzip

    在 Firebug 中 请求标头具有以下条目 接受编码 gzip deflate 但没有 内容编码 gzip在响应标头中 无论我尝试过什么 根据SO和其他网站上的许多答案 似乎没有任何效果 静态文件和动态文件都没有被压缩 或者至少如果它们被
  • 在 Boto3 中,如何使用附加关键字参数为 list_objects 创建分页器?

    我正在使用一个Paginator迭代 S3 存储桶的内容 以下http boto3 readthedocs io en latest guide paginators html creating paginators client boto
  • 如何从 Perl 调用 PHP 脚本?

    如何从 Perl 脚本调用 PHP 脚本并以变量形式获取其输出 使用反引号运算符 my phpOutput usr bin php cli your script php 请注意 您可能需要编辑路径以指向您的php可执行的 如果您想将输出作
  • jQuery跨域请求响应头

    我正在使用 html 数据类型发出跨域 ajax 请求 正如我所包括的那样 它们工作正常 Access Control Allow Origin 在服务器的响应中 问题是我需要从服务器的响应中获取某些标头 无论我做什么 除了 内容类型 之外
  • OpenCL 用户定义的内联函数

    是否可以在 OpenCL 代码中定义我自己的函数 以便内核可以调用它们 是的 我在哪里可以看到一些简单的例子 用于创建程序的函数是 cl program clCreateProgramWithSource cl context contex
  • GitLab CI 由于 maven-surefire-plugin 和虚拟机崩溃而失败

    我们有大约 10 个不同的应用程序 它们是使用 Groovy 的 Spring Boot 项目 我们所有的项目都在所有开发人员工作站中正确构建 并且直到昨天它们都正常运行 但是今天突然所有项目仅在我们的 GitLab CI 管道中停止工作
  • 如何从抓取的链接下载 PDF [Python]?

    我正在用 Python 制作 PDF Web Scraper 本质上 我试图从我的一门课程中抓取所有 PDF 形式的讲义 我想输入一个网址 然后获取 PDF 并将它们保存在我的笔记本电脑的目录中 我已经看过几个教程 但我不完全确定如何去做
  • 重新安装 python 2.7.12 和 python 3.5.2

    晚上好 今天我在尝试安装 python 3 5 2 的一些软件包时弄乱了我的笔记本电脑 我尝试安装正确的 pip 版本 但我错过了一些东西 现在我无法在两个版本中安装任何软件包 并且无法解决问题 是否可以卸载 2 个版本 包括所有软件包 并
  • 如何隐藏 html 源并禁用右键单击和文本复制?

    以下网站已禁用右键单击和查看源代码 http www immihelp com visitor visa sponsor documents html 任何人都可以阐明这是如何可能的吗 以下网站已禁用右键单击和查看源代码 他们愚弄了你 只需
  • dispatch_async 是否复制内部块

    鉴于以下情况 手动引用计数 void block void NSLog wuttup void async block void block dispatch async dispatch get main queue async bloc