block实战讲解(2)

void testBlockArray() {
  int val = 10;
  NSArray *arr = [NSArray arrayWithObjects:^(){NSLog(@"blk0:%d", val);},^(){NSLog(@"blk1:%d", val);}, nil];
  NSLog(@"%@", arr);
  
}
        // If we are type-erasing a block to a block-compatible
       // Objective-C pointer type, we may need to extend the lifetime
       // of the block object.
       if (typeArgs && Args[i]->isRValue() && paramType->isBlockPointerType() &&
           Args[i]->getType()->isBlockPointerType() &&
           origParamType->isObjCObjectPointerType()) {
         ExprResult arg = Args[i];
         maybeExtendBlockObject(arg);
         Args[i] = arg.get();
       }
     }
   }
 bool Sema::CheckMessageArgumentTypes(
     const Expr *Receiver, QualType ReceiverType, MultiExprArg Args,
     Selector Sel, ArrayRef<SourceLocation> SelectorLocs, ObjCMethodDecl *Method,
     bool isClassMessage, bool isSuperMessage, SourceLocation lbrac,
     SourceLocation rbrac, SourceRange RecRange, QualType &ReturnType,
     ExprValueKind &VK) 
 /// Do an explicit extend of the given block pointer if we're in ARC.
 void Sema::maybeExtendBlockObject(ExprResult &E) {
   assert(E.get()->getType()->isBlockPointerType());
   assert(E.get()->isRValue());
 
   // Only do this in an r-value context.
   if (!getLangOpts().ObjCAutoRefCount) return;
 
   E = ImplicitCastExpr::Create(Context, E.get()->getType(),
                                CK_ARCExtendBlockObject, E.get(),
                                /*base path*/ nullptr, VK_RValue);
   Cleanup.setExprNeedsCleanups(true);
 }

在ARC环境下,下面的代码的执行结果是什么?

-(NSArray*) getBlockArray
{
  int num = 916;
  return [NSArray arrayWithObjects:
          ^{ NSLog(@"this is block 0:%i", num); },
          ^{ NSLog(@"this is block 1:%i", num); },
          ^{ NSLog(@"this is block 2:%i", num); },
          nil];
}

- (void) forTest
{
  int a = 10;
  int b = 20;
}

- (void)test
{
  NSArray*  blockArr = [self getBlockArray];
  [self forTest];

  void (^blockObject)(void);
  for(blockObject in blockArr){
    blockObject();
  }

答:

输出  this is block 0:916  后闪退

解析:

arrayWithObjects  方法只会copy第0个block,导致该block的类型修改为**NSMallocBlock**,后面的block被保持初始类型  NSStackBlock  并会在后续被系统回收内存。后面的for循环调用该指针时,会因为野指针而crash。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容