当我尝试读取NSString时,我得到一个“EXC_BAD_ACCESS”

时间:2010-04-17 20:04:58

标签: iphone nsstring exc-bad-access

这是我的iPhone代码的(非常)简化版本:

  

@interface x {
      NSString * name1;
      NSString * name2;
  }

     

-init {
      name1 = @“”;
      name2 = @“”;
  }

     

- (无效)a {
      Foo * foo = [Foo alloc];
      name1 = @“uhuh”;
      name2 = [foo bar]; //返回一个(NSString *)
      [foo release];
  }

     

- (无效)b {
      NSLog(@“%@”,name1); //它有效       NSLog(@“%@”,name2); //我得到一个EXC_BAD_ACCESS ...
  }

为什么我有这个问题?我该如何解决呢? 谢谢!

编辑:我正在解决问题,我忘记了“保留”......

3 个答案:

答案 0 :(得分:1)

您需要阅读Cocoa Memory Management Guide

您在代码中所做的一些事情表明您没有掌握可可内存管理的基本概念。

例如:

[Foo alloc];

你没有初始化'foo'。将allocinit个调用结合在一起是很常见的做法,例如:[[Foo alloc] init];这将确保对象成员和状态是您在创建后所期望的。

name2 = [foo bar]; // returns a (NSString *)

bar方法可能会返回autoreleased字符串。在将其分配给name2之后,您不会保留它,因此在方法返回后的某个时间它将被释放。这就是你的代码崩溃的原因。您正在尝试访问已释放的对象。 name2指向的对象已释放并取消分配,但指针未设置为nil,这意味着它指向的内存现在可以包含任何内容。这是未定义的。

name1正在起作用的原因是因为在Cocoa中使用文字@“”字符串需要特别考虑。当像这样使用字符串时,它变为“内化”。如果您创建两个包含相同文本的文字字符串,系统将对其进行优化,以便这两个字符串都指向内存中的一个对象。

也就是说,如果您的代码如下所示:

NSString *myString1 = @"hello";
NSString *myString2 = @"hello";

NSLog(@"string1: %p, string2: %p", myString1, myString2);

这会产生如下消息:string1: 0x123456, string2: 0x123456。这里要注意的重要一点是内存地址是相同的。字符串指向同一个对象,即使它们是代码中的不同实例。

答案 1 :(得分:0)

昨天我收到了一个EXC_BAD_ACCESS错误。原来我在一个对象上调用release导致它被删除,然后我尝试使用它。

你没有打算release任何你不应该做的事情吗?

只是一个友情提醒:如果您未在某个对象上致电allocretain,则不会致电release。使用您提供的代码,似乎不会出现问题。但是为了以防万一,我想指出这一点。

答案 2 :(得分:0)

乔尔是对的。 试着查看你的[foo bar]函数,可能在你正在释放任何对象的那个函数中