Objective c 使用block getter消息时出现Seg故障

Objective c 使用block getter消息时出现Seg故障,objective-c,cocoa-touch,objective-c-blocks,Objective C,Cocoa Touch,Objective C Blocks,我不熟悉街区。我试图在命令行中运行这段代码,以了解块是如何工作的。当我通过命令行运行代码时,我得到一个Seg错误。但是当我使用Xcode运行相同的代码时,它编译并运行得很好。代码如下:- #import <Foundation/Foundation.h> @interface BlockTest:NSObject @property (copy) void (^block) (void); -(void)run; @end @implementation BlockTest @

我不熟悉街区。我试图在命令行中运行这段代码,以了解块是如何工作的。当我通过命令行运行代码时,我得到一个Seg错误。但是当我使用Xcode运行相同的代码时,它编译并运行得很好。代码如下:-

#import <Foundation/Foundation.h>

@interface BlockTest:NSObject
@property (copy) void (^block) (void);
-(void)run; 
@end

@implementation BlockTest
@synthesize block;
-(void)run{
   NSObject *obj= [[NSObject alloc] init];

   block = ^void (void){
   NSLog(@"my object- %@",obj);
   };

 NSLog(@"running the block...");
 block();
}
@end

int main(){
  BlockTest *test= [[BlockTest alloc] init];
  [test run];
  NSLog(@"%@",[test block]);
}
#导入
@接口块测试:NSObject
@财产(副本)无效(^块)(无效);
-(无效)运行;
@结束
@实现块测试
@合成块;
-(无效)运行{
NSObject*obj=[[NSObject alloc]init];
块=^void(void){
NSLog(@“我的对象-%@”,obj);
};
NSLog(@“运行块…”);
block();
}
@结束
int main(){
BlockTest*test=[[BlockTest alloc]init];
[试运行];
NSLog(@“%@,[试块]);
}
以下是我在Xcode中运行它时的输出:-

2015-01-03 23:13:41.187区块测试[999:41316]运行区块

2015-01-03 23:13:41.189区块测试[999:41316]我的目标

2015-01-03 23:13:41.190区块测试[999:41316]

但是,当我在命令行中运行它时,我得到以下结果:-

2015-01-03 23:32:50.441区块测试[1115:47957]运行区块

2015-01-03 23:32:50.443区块测试[1115:47957]我的目标-

分段错误:11


我怎么会有Seg故障??请帮忙。Thanx

缺少详细信息,例如您使用的是MRC还是ARC?所以这里有一个猜测

当您这样做时:

block = ^void...
如果将直接赋值给属性的支持变量,这将绕过
copy
属性的语义。如果未复制该块,则当
run
返回时,该块将被销毁,然后将出现内存故障

改为:

self.block = ^void...
以便使用属性设置器并完成复制

顺便说一句:现在你不需要
@synthesis
,属性将自动创建,并使用名为_property的支持变量。通常,您应该始终使用self.property设置属性,因为它支持KVO和
copy
属性。您还应该确保使用的是ARC

附录

从评论(关于此问题和主要问题)可以看出,您正在使用不同的编译器编译代码,以便在命令行上运行。这似乎可以解释这些差异

如果没有ARC,则必须如上所述使用
self.block=…
,以便应用属性的
copy
。使用ARC时,即使特性设定器本身被绕过,ARC也会插入块副本作为指定的一部分


在这两种情况下,您都应该使用当前版本的Xcode/Clang编译器进行编译。如果在Xcode中将项目类型选择为“命令行工具”,则生成的二进制文件是命令行二进制文件。要快速找到它,您可以右键单击Xcode中的二进制名称,然后选择“在Finder中显示”。在终端上运行二进制文件,它就会工作。

当你说“在命令行上运行”时,你是什么意思?在这两种情况下,您是否以相同的方式编译它?所谓“在命令行中运行”,我的意思是使用gcc llvm编译器编译它,然后运行生成的二进制文件。llvm-gcc不支持ARC。只有LLVM-Clang可以。另外,LLVM-GCC是古老的;在Xcode 5及以上版本中,它只是重定向到LLVM Clang。当您在命令行上编译ARC时,是否确实使用
-fobjc ARC
标志或其他东西启用了ARC?请注意,这只会解释在他使用MRC时发生的崩溃。但是第一个输出(“在Xcode中”)似乎指示ARC,因为它显示NSMallocBlock,但没有任何东西会复制MRC中的块。也许他在其中一个中使用了ARC,在另一个中使用了MRC。@newacct-我对此也感到困惑,因此“猜测”;-)@rahulbsb-您可能没有使用ARC,请参阅附录。@rahulbsb-当块是一个对象时,使用了一种优化,允许在本地堆栈上创建它们,而不是在堆上创建其他对象,当堆栈在方法返回时展开时,堆栈上分配的任何内容都会消失。在ARC下,此优化与任何其他优化一样进行处理-程序员实际上看不到它,堆栈块会根据需要复制到堆中,以保持其正确的生存期。在旧版编译器/MRC下,程序员可以看到优化,并且必须根据需要手动复制块-复制属性是一种方式。@rahulbsb-在堆栈上存储块是一种优化,编译器可以选择在堆栈上存储块,但不要求这样做。在MRC下,程序员需要了解优化,必须假设它总是被使用,并根据需要插入副本。有些副本可能是多余的,但你不知道它们会。。。