1

我使用了块和 ARC,发现在某些情况下,iOS 仅在发布版本中崩溃。像这样写代码是错误的。

-(IBAction)clickedButtonA:(UIBarButtonItem*)sender event:(UIEvent*)event {
  NSMutableArray *arrRows = [NSMutableArray arrayWithCapacity:0];
  #warning this code only crash on Release Build.... Don't use this
  NSMutableDictionary * dicRow = [NSMutableDictionary dictionaryWithCapacity:0];
  [arrRows addObject:dicRow];
  dispatch_block_t block = ^{
    NSString *str = [NSString stringWithFormat:@"%@",[_tweet valueForKey:@"text"]];
    [[UIPasteboard generalPasteboard] setString:str];
  };
  [dicRow setValue:block forKey:kDicKeyLinkPopBlock];

  NSMutableArray *sections = [NSMutableArray arrayWithObject:arrRows];
  TOVLinkPopoverViewController *controller= [[TOVLinkPopoverViewController alloc] init];
  controller.arrayLink = sections;
}

而从其他控制器,当我访问该块时,它只会在我发布版本时崩溃。我知道你需要复制块

[dicRow setValue:[block copy] forKey:kDicKeyLinkPopBlock];

对于像 NSMutableDictionary 这样的非块感知类。

问题是“为什么它只在发布版本时崩溃?” 我知道这个“应该崩溃”,这是使用块的错误方式,但希望它在 Debug 构建时崩溃,这样我们就可以更早地找到这种错误。

还有一个问题是“是否有任何构建设置使此代码在调试构建时崩溃?”

您可以从 gitHub 运行示例代码, https://github.com/tomohisa/iOS_PopoverMenu_Notification

See ViewController.m and find commented out code (only crash on release).

4

1 回答 1

6

You're right that you need to add [block copy]. This is because that block is created in the current stack frame (i.e. within clickedButtonA:event:) but then you add it to a dictionary and presumably pull it out later. When you pull it out later and use it, that original stack frame has gone and you will have a pointer to some random memory that might not (most likely won't) actually be the block any more.

When you copy the block, if it's on the stack currently then it gets copied to the heap and if it's already on the heap then it just retains it. This means that you now have a block which can be passed around between contexts and will be valid.

The reason that you are only seeing it crash in release mode is because release mode will be turning on compiler optimisation that is completely changing how the stack is handled. Probably you were very lucky in debug mode not to see the problem and was simply a quirk of how your app is designed.

于 2012-05-20T20:56:16.560 回答