返回位于本地堆栈上的块

2024-02-19

clang 分析器可以检查返回的基于堆栈的内存。

dispatch_block_t getPrintBlock (const char *msg) {
    return ^{
        printf("%s", msg);
    };
}

引发此错误:returning block that lives on the local stack

这个错误是什么意思?


该错误意味着您返回的值在方法返回后将无效。这不仅仅是块的问题,请考虑:

- (int *) badMethod
{
   int aLocalIntVariable;

   return &aLocalIntVariable; // return a reference to aLocalIntVariable, but that variable is about to die...
}

局部变量在进入方法时创建,它们所在的地方称为“堆栈”。当方法返回时,这些局部变量将被销毁。您可以返回一个value在这样的变量中,但你不能返回参考变量本身 - 它将是无效的。您可以将对局部变量的引用传递给您调用的方法,因为在这种情况下您的局部变量仍然存在。

在你的情况下,你已经创建了一个块。 Objective-C 碰巧在堆栈上创建块值,即有效地在匿名局部变量中创建块值,并使用引用来引用它们。您可以将这样的引用传递给您调用的方法,但不能返回它 - 该匿名局部变量会像其他任何变量一样被销毁。

然而,Objective-C 提供了两种方法来创建块值的副本作为对象,该副本存在于“堆”上,并且比其创建者的寿命更长。首先有Block_copy这是一个函数:

<reference to heap allocated block> = Block_copy(<reference to stack allocated block>);

这是执行此操作的原始方法,并且受到所有支持 - 包括在纯 C 代码中,块是 C 的一部分,而不仅仅是 Objective-C。第二种方式pretends该块已经是一个对象,允许您发送标准copy信息:

<reference to heap allocated block> = [<reference to stack allocated block> copy];

如果您主要是 Objective-C 人员,那么第二种方法可能会感觉更舒服,但确实模糊了为什么需要它的问题。

ARC 在这里很有帮助,在自动化内存管理中,它会自动将块从堆栈复制到堆(至少在当前的编译器中,它在早期的编译器中可能无法正常工作),因此程序员可以忽略真正的实现细节。

附录:ARC

上面的最后一段是由 @newacct 提出的,并产生了很长的问答评论交换。为了使其中的信息更易于理解,我们删除了评论,并将此处的信息合并为附录。

在理解 ARC 如何处理块时,有两个文档很有用:

  1. Objective-C 自动引用计数 http://clang.llvm.org/docs/AutomaticReferenceCounting.html,特别是第 3 节(块是可保留对象指针)、3.2.3(可保留对象类型跨返回边界有效)和 7.5(块复制时的规则)。
  2. 过渡到 ARC 发行说明 http://developer.apple.com/library/mac/#releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.html,特别是常见问题解答项目“块在 ARC 中如何工作?”

从这些可以确定大多数时候作为所有对象类型管理的一部分,ARC 将处理从堆栈到堆的所有块复制。

第二个参考文献强调了一种情况,至少在编写文档时,没有自动处理这种情况。这种情况是将堆栈分配的块传递给类型的方法参数id,例如就像是:

- (void) takeBlockWithTypeLoss:(id)block { ... }

[obj takeBlockWithTypeLoss:^{ ... }];

在这种情况下,在写入文档时,ARC 不会复制该块。如果被调用的方法随后执行保留传递的块的操作,则会出现问题,因为保留值不在堆上。 (请注意,需要为该块分配堆栈才能出现问题。不引用环境中变量的文字块是静态分配的,首先存储在具有默认强所有权的局部变量中,然后传递给方法的文字块也会被复制。)

这种情况是类型丢失的示例,已知为块类型的值被传递为id丢失类型信息。编译器总是可以确定这些点,那么为什么 ARC 不复制该块呢?过去给出的答案很简单,一个是效率,一个是复制may不需要,并且大量不需要的副本会影响性能。

However当前编译器(Xcode 4.6.1)appears为了处理剩下的一种情况,在类型丢失时将一个块复制到堆中。如果任何人都可以证明这一点现在已记录(或者您确信您的编译器可以处理这种情况,例如通过编码检查),那么它会出现Block_copy() (or [block copy])可以被归入历史,如果没有,那么当发生类型丢失时应该使用它。

附录:2013 年 6 月

据透露这个问题 https://stackoverflow.com/questions/17000926/some-questions-about-objective-c-block-and-copy有一种情况是 Xcode 4.6.3/Clang 4.2 这样做not处理。当一个块作为变量参数之一传递给可变参数方法时,编译器不会自动将堆栈块提升到堆。这是上面提到的类型丢失的一个子情况。

因此,存在当前编译器无法处理的情况,这表明编译器支持超出规范的内容未记录的原因 - 支持不完整(尽管这些并不是理论上的原因)。

因此,和以前一样,如果存在类型丢失,则编译器可能不会自动处理块升级(但如果需要,可以对此进行测试),不涉及类型丢失的情况将根据规范自动处理。

(顺便说一句。老问题 https://stackoverflow.com/questions/6147940/blocks-and-stack对上述问题的评论中提到的现在是规范涵盖的情况之一,并由编译器正确处理。)

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

返回位于本地堆栈上的块 的相关文章

  • UIDocumentInteractionController 阻止“打开方式”表中的空投

    在我的应用程序中 我允许用户通过 Instagram 分享照片 这需要使用 UIDocumentInteractionController 如果手机支持 则会自动检测空投 如何将其从 打开方式 操作表中删除 即使我使用 UIActivity
  • 自定义 UITableViewCell 选择样式?

    当我点击我的UITableViewCell 当我单击单元格时 背景部分 我的背景图像未覆盖的区域 会变成蓝色 另外 所有的UILabel单击时单元格上的 s 变为白色 这就是我想要的 然而 我不想要的是当我点击它时的蓝色背景 但如果我这样做
  • 如何解决 CoreData mogenerator 未找到问题

    我收到如下所示的错误 我不知道我错过了什么 我该如何解决这个问题 如下图所示 Users nischalhada Documents XcodePro mnepalnews revisited 2 0 CoreData mogenerato
  • 拖动时获取MKAnnotation的坐标

    我正在根据用户添加的注释的位置创建一条路径 MKPolyline 我想允许用户通过拖动引脚来更改路径 我目前可以做到这一点 但 MKPolyline 不会更新 直到引脚被放下 我实施了 void mapView MKMapView mapV
  • 我如何获取用户的电子邮件? iPhone SDK

    我需要获取 Mail app 中使用的用户的电子邮件地址 如何使用 iPhone SDK 做到这一点 谢谢你 简短的回答 你不能 如果需要 您应该提示用户输入电子邮件地址
  • 如何检查 BOOL 是否为空?

    有没有办法在将值分配给 BOOL 之前检查该值是否为 NULL Nil 例如 我在 NSDictionary 中有一个值可以是 TRUE FALSE NULL mySTUser current user following results
  • 如何使用MKMapView完成加载委托,可能的“完成显示”委托?

    当用户在选择注释后点击 保存 时 我尝试保存地图视图的缩略图 当用户尚未放大该注释时会出现问题 因此尚未加载关闭缩放级别 这就是用户点击保存后我正在做的事情 将布尔值 saving 设置为 true 居中并放大注释 无动画 当调用mapVi
  • CBPeripheral 名称有时为 null

    我正在开发一个应用程序来与蓝牙 LE 外围设备进行通信 我目前正在测试的外围设备是其中之一these http www ti com tool cc2540dk mini 有趣的是 有时当我发现它时 我会得到它的正确名称 SimpleBLE
  • 如何在 UICollectionView 的节标题中动态添加标签和按钮?

    请帮助我如何水平添加标签和水平添加类似的按钮 但每个按钮应像另一个部分一样在每个标签的下方对齐 这应该在 UICollectionView 的标题中动态发生 因为标签和按钮的数量根据我的数据 我想制作一种 Excel 类型的布局 并在标题中
  • iOS 10 的错误? NSDate 日本地区时间描述和 24 小时休息

    这似乎是 iOS 10 的一个错误 在 iOS 8 和 9 中都可以 NSDate date description 的小时描述是错误的 它附加了 24 小时描述和 12 小时描述 我没有使用 NSDateFormatter 只是默认设置
  • 为什么 Xcode 4 不会对我未完整实现 UITableViewDataSource 协议发出警告?

    如果我在 Xcode 中使用以下代码声明并不完全实现我自己的协议 一些协议 h protocol SomeProtocol
  • 适用于 Objective-C / iPhone 的良好 HTTP 库? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 UPDATE 这个问题显然已经过时了 参见日期 我建议只使用现代 iOS7 功能 例如 NSURLSession 我想 这个问题是为了历史
  • 我应该在哪个方法中设置 UITextField 的委托?

    在 viewDidLoad 或 init 方法中设置 UITextField 的委托是一个好习惯吗 我尝试在 init 方法中将委托设置为 self 但它没有调用相应的委托方法 当我将代码移动到 viewDidLoad 中时 它注册为将 s
  • Objective-C 中 typedef 枚举语句在哪里?

    我担心的一个基本问题 以下代码有效 并且 typedef 枚举被识别 但我收到一条警告消息 空声明中无用的存储类说明符 我在这里做错了什么吗 这是放置 typedef 枚举的最佳位置吗 import
  • iOS 以编程方式将 AVI 转换为 MP4 格式

    我的应用程序中有一个查询 因为我想将 AVI 格式的视频转换为 MP4 电影格式 所以有没有什么方法可以以编程方式执行此操作 任何代码片段将不胜感激 你需要使用AVAssetExportSession将视频转换为 mp4格式 下面方法转换
  • 如何在 Swift 中调用 Objective-C 实例类型方法?

    我有一个 Objective C 类 如下所示 interface CustomObjectHavingData NSObject property nonatomic strong NSData objWithData instancet
  • 使用 Objective-C 进行 Windows 开发

    最近读了一篇关于 Objective C 的文章 我觉得它是一门相当简洁的语言 具有很多很酷的功能 我无意进行任何 iPhone 开发 但是我了解 GCC 能够编译 Objective C 代码 所以我想知道 Objective C 是 W
  • 如何在 xcode 中使用相同的 nib 文件创建多个窗口

    我有一个使用表格视图作为界面的 iPhone 应用程序 每次用户点击其中一个表格单元格时 我想向用户显示另一个窗口 然而 我推入导航控制器的窗口的用户界面非常相似 因此 我决定制作一个 通用 nib 文件 以便在该通用 nib 文件的文件所
  • 使用 Objective C 将 RGB 彩色图像更改为灰度图像

    我正在开发一个将彩色图像更改为灰度图像的应用程序 然而 有些图片显示出来是错误的 我不知道代码有什么问题 也许我输入的参数有误 请帮忙 UIImage c UIImage imageNamed downRed png CGImageRef
  • 如何连续关闭 2 个模态视图控制器?

    我有 2 个以模态方式呈现的视图控制器 A presents B which presents C 当我解雇C时 我也想解雇B 但我不知道该怎么做 解雇C self dismissModalViewControllerAnimated YE

随机推荐

  • 在 T-SQL 中将特定 BigInt 转换为 DateTime

    我有 bigInt 635307578922100000我需要转换成DateTime 我尝试了几种方法来做到这一点 SELECT DATEADD S CONVERT bigint 635307578922100000 1000 CONVER
  • SPSite 站点 = new SPSite(SPContext.Current.Web.Url) 与 SPContext.Current.Web.Site

    为什么某些 SharePoint 示例使用 using SPSite site new SPSite SPContext Current Web Url 而不仅仅是简单地 SPSite site SPContext Current Web
  • 如何使用DELPHI更改Android设备通知中的小图标图像

    有没有办法用Delphi更改Android应用程序通知中的小图标图像 默认使用的应用程序图标 轻松创建通知的标准方法是 var aNotification TNotification begin aNotification aNotific
  • 在C++中查找进程中加载​​的DLL的内存地址

    我有一个正在使用 Test dll 的正在运行的进程 我想知道内存中 Test dll 开始的确切内存位置 但似乎无法 我的主要问题是我需要写入此 DLL 的偏移量 但当我使用 Read WriteProcessMemory 时 我无法准确
  • 为什么 MassTransit 消息传递中不允许使用结构体?

    消费者界面在MassTransit所有人都期望消息模型是类而不是结构 由于它们都是内部接口 我必须说那里的设计非常好 这是显示约束的通用容器类 直接获取从源代码来看 https github com MassTransit MassTran
  • C++ 打印当前函数输入参数类型、名称和值

    我正在寻找一种允许记录函数输入参数的功能 例如 void func std string input name const int n print current function s inputs type name and value
  • 获取 i18next 以回退到“无翻译”

    如果没有找到该键的翻译 默认情况下 i18next 翻译库似乎会回退到翻译键 例如 No translation defined for CANCEL yet i18next t CANCEL Returns CANCEL 如果没有找到该密
  • 如何动态创建变量? [复制]

    这个问题在这里已经有答案了 我想在Python中动态创建变量 有没有人有任何创造性的方法来做到这一点 除非非常需要创建一堆变量名称 否则我只会使用字典 您可以在其中动态创建键名称并将值与每个名称相关联 a k 0 while k lt 10
  • 将一组 NumPy 数组传递到 C 函数中进行输入和输出

    假设我们有一个 C 函数 它接受一组一个或多个输入数组 处理它们 并将其输出写入一组输出数组 签名如下所示 count表示要处理的数组元素的数量 void compute int count float input float output
  • 使用 Webpack 和 ES6 的 Fine Uploader

    我正在尝试将 Fine uploader 与通过 Webpack 捆绑的 React ES6 应用程序集成 寻找有关如何将精细上传器包含在此堆栈中的指导 In my webpack config js我为 Fine Uploader 设置了
  • 在javascript中使用单引号传递变量

    我对链接进行了 onClick 调用 a this is working good 问题是 fomateName 内的变量将包含单引号 而我的 fomateName 采用如下变量 var a Andrew D souza 需要格式化用单引号
  • 定义指向 const 字符串的 const 指针

    阅读了 Ulrich Drepper 的博文 发现两个条目看起来相互矛盾 In the 第一 http udrepper livejournal com 13851 html 全局空间中的字符串 Ulrich 指出该字符串应定义为 cons
  • Linux下如何用C写文件?

    我想重写Linux的 cp 命令 所以这个程序会像这样工作 a out originalfile copiedfile 我可以打开文件 创建新文件 但无法写入新文件 什么也没写 可能是什么原因 当前的C代码是 include
  • 无法将类型“TEnum”转换为“int”

    我正在尝试将枚举转换为列表 如中所述this https stackoverflow com questions 3489453 how can i convert an enumeration into a listselectlisti
  • 降低 jquery UI 中手风琴的速度

    我对这段代码有两个问题 首先我想降低效果的速度 其次 就像您对效果进行操作以关闭选项卡一样 然后将出现以下新选项卡 if sidebar ul length sidebar ul accordion event mouseover acti
  • 从 SQLite 中的 INSERT OR IGNORE 语句查找自动递增值

    我有一个名为 图像 的表 CREATE TABLE images id INTEGER PRIMARY KEY AUTOINCREMENT url TEXT NOT NULL UNIQUE caption TEXT 插入行时 我希望 URL
  • `npm install` 和 `npmaudit` 计数之间的区别?

    最近添加后npm audit 用于审核依赖关系 我注意到有多少个包之间存在巨大差异added 安装在node modules 以及有多少个audited by npm 这是一个例子 这是我的问题 我说得对吗281已安装的软件包总数是多少 W
  • Selenium 单击与文本对应的 JavaScript 按钮

    我的网页中有很多按钮 它们也是 javascript 按钮 所有这些按钮都有相同的 TagName 但 id 不同 但我不能使用 ID 因为我无法预测必须单击哪个按钮 Selenium 将搜索内容 问题here https stackove
  • 在网络上创建电子邮件表单时的安全注意事项

    我知道我必须考虑 邮件头注入 还有更多的事情吗在发送表格邮件之前我需要知道吗 我想要邮件 我觉得我必须设置表单邮件在我的页面上 但我听说邮件事情很危险 如果我 不考虑所有安全问题 1 避免垃圾邮件 使用验证码或其他东西来防止垃圾邮件 链接谈
  • 返回位于本地堆栈上的块

    clang 分析器可以检查返回的基于堆栈的内存 dispatch block t getPrintBlock const char msg return printf s msg 引发此错误 returning block that liv