【问题标题】:String comparison in Objective-C with isEqualToStringObjective-C 中的字符串比较与 isEqualToString
【发布时间】:2010-10-19 20:48:59
【问题描述】:

我有一行代码导致“EXC_BAD_ACCESS”错误。该行代码如下(格式化为一行,为了便于阅读去掉了嵌套代码)。

if (![sendData isEqualToString:@"-"]){ ... }

实际错误发生在 IF 行。奇怪的是,如果我在该行上放置一个断点,则 NSString 称为 sendData(显示为 NSCFString,其值为“-”,不带引号)。为什么会导致错误?

【问题讨论】:

  • 我意识到当我在我的 appDelegate 头文件中声明属性 sendData 时,我没有使用“retain” - 但是我改变了它并且仍然收到错误。奇怪的是,我使用其他属性的方式与这个相同,而这个是唯一产生错误的属性。

标签: ios objective-c nsstring string-comparison


【解决方案1】:

听起来您正试图向内存已被释放的对象发送消息。确保您遵循Memory Management Programming Guide for Cocoa 中讨论的正确内存管理技术。解决方法可能是在其被释放之前的某个时间点添加一个[sendData retain],但要了解其原因,您必须阅读上述指南。

【讨论】:

  • 我不知道为什么会这样。 sendData 是 AppDelegate 的一个属性,根本没有被释放(由我)。另外,如果对象被释放,我还能在调试器中看到它的值吗?
  • 你在 sendData 中获取或创建数据吗?如果是这样,您可能需要调用 retain。
  • 我正在创建如下数据:sendData=@"-";
【解决方案2】:

要解决这个问题,您必须在所有回调方法中设置断点。

问题很简单,代码试图访问它找不到的内存。

找到那行代码比较困难,因为回调不是按顺序调用的。

  1. 添加更多断点
  2. 添加更多 NSLog(..)
  3. 考虑捕获异常(请参阅throwing an exception in objective-c/cocoa

从控制台输出:

Attaching to program: `/Users/rjstelling/Library/Application Support/iPhone Simulator/User/Applications/C04A40BB-1D98-402E-BBEF-37E6FB860089/TwoViewApp.app/TwoViewApp', process 24032.
Re-enabling shared library breakpoint 1
2009-04-16 16:16:45.830 TwoViewApp[24032:20b] stream event 1
2009-04-16 16:16:45.831 TwoViewApp[24032:20b] on input stream
2009-04-16 16:16:45.831 TwoViewApp[24032:20b] stream event 1
2009-04-16 16:16:45.832 TwoViewApp[24032:20b] on output stream
2009-04-16 16:16:45.832 TwoViewApp[24032:20b] stream event 4
2009-04-16 16:16:45.832 TwoViewApp[24032:20b] on output stream
2009-04-16 16:16:45.833 TwoViewApp[24032:20b] stream has space open
(gdb) continue
2009-04-16 16:17:06.405 TwoViewApp[24032:20b] We made it - ok!
2009-04-16 16:17:06.406 TwoViewApp[24032:20b] stream event 2
2009-04-16 16:17:06.406 TwoViewApp[24032:20b] on input stream
2009-04-16 16:17:06.407 TwoViewApp[24032:20b] Processing: +OK CONN PinkNotes® Plus Master v5.00.26 Beta (v4 compatible)
:tPNPStr
2009-04-16 16:17:06.407 TwoViewApp[24032:20b] SendData= USER (null):tPNPStr
Current language:  auto; currently objective-c
Program received signal:  “EXC_BAD_ACCESS”.
(gdb) 

问题发生在ProcessData 中或之后的某个地方,我认为这是一个回调。尝试在 TwoViewAppAppDelegate.m 的第 157 行附近放置一个断点


如果您添加,这不是导致EXC_BAD_ACCESS 的那一行:

else
{
    NSLog(@"We made it - ok!");
}

到 if() 语句,你可以看到它通过了if ( ![sendData isEqualToString:@"-"] ){...}

从方法调用返回时会发生错误。


好吧,这可能会有所帮助:

如果您使用@"My string" 创建字符串,如果它们具有相同的内容,编译器会将它们映射到他的相同内存,即:

NSString *var1 = @"string1";
NSString *anotherstring = @"string1";
NSString *morestringivars = @"string1";

都会指向同一个内存空间。

这可能会有所帮助,但我不确定如何?也许您可以发布更多代码,以便我可以在我的设置上运行它。


请记住,在 iPhone 上的事件周期开始时会创建一个自动释放池。

因此,最好在将 sendData 分配给 ivar 后立即在 sendData 上调用 autorelease。

...

[sendData autorelease];

...

【讨论】:

  • 如果您想看一下,我很乐意发布代码以供下载。
  • 它在我的系统上肯定可以。奇怪。
  • 它奇怪的 b/c 我只是踩过它(第 100 次),它确实踩过 IF - 然后我再次运行它,它又没有。很奇怪。
  • 这是 b/c 回调函数在不同时间被调用,具体取决于网络。
  • 那你有什么推荐的?似乎取决于我将断点放在哪里,现在不同的行会导致问题....我不应该使用属性吗?有没有办法以其他方式声明一个可以从文件中的所有函数访问的公共 NSString?
【解决方案3】:

在发布后将您的对象设置为 nil,以防止在向不可用的对象发送消息时崩溃。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-02-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多