iOS指南系列:如何解决奔溃问题-关于内存访问续

来源:互联网 发布:dojo中js方法跳转页面 编辑:程序博客网 时间:2024/06/05 19:46

Messing with Memory:

iOS指南系列:如何解决奔溃问题

iOS指南系列:如何解决奔溃问题-关于内存访问

iOS指南系列:如何解决奔溃问题-关于内存访问续

iOS指南系列:如何解决奔溃问题-关于内存访问续


你知道演练过程了运行程序点击按钮等待崩溃没错!

The app crashes on NSLog().

又来一内存访问错误的问题 EXC_BAD_ACCESS, yikes! 幸运的是,Xcode中显示了你究竟在何处发生崩溃,在 buttonTapped: 方法:
NSLog("You tapped on: %s", sender);

有时,这些错误可能需要在你的头脑里片刻或再度思考下但同样,Xcode了援助之手 - 只需轻按黄色三角形看到什么是错的提示

Objective-C strings must have a @ prefix.

NSLog() 采用 Objective-C-type string, 不是过去的 old C-string, 需要插入 @ w :

NSLog(@"You tapped on: %s", sender);

你会发现黄色三角形警告没消失这是因为此行的另一个错误可能会或可能不会导致您的应用程序崩溃,这些都是有趣有时代码工作得很好least appears工作得很好 - 在其他时间它会崩溃 当然这些各种各样崩溃发生在客户的设备从未自己
让我们来看看新的警告什么

Xcode warns about a format string issue.

这个 %s 指定是用于变量类型 C-style strings. C-string 通常就是代表一段内存的字符内容,字符以数组方式存在,需要一个终止符号,通常是 “NUL character,” 通常代表了 0. 举个例子来说 C-string “Crash!” 在内存中的布局类似:

What a C-string looks like in memory.

Whenever you use a function or method that expects a C-style string, you have to make sure the string ends with the value 0, or the function will not recognize that the string has ended.

Now, when you specify %s in an NSLog() format string – or in NSString’s stringWithFormat – then the parameter is interpreted as if it were a C-string. In this case, “sender” is the parameter, and it’s a pointer to a UIButton object, which is definitely not a C-string. If whatever “sender” points to contains a 0 byte, then the NSLog() will not crash, but output something such as:

每当你使用一个函数或方法,预计会用到C风格的字符串你必须确定使0值作为字符串结束,否则程序不会承认已经结束的字符串的位置,一直读下去
现在,当您指定NSLog)格式字符串S - NSString的stringWithFormat - 那么该参数被解释为 它是一个C字符串在这种情况下“sender参数它是一个UIButton对象,绝对不是一个C字符串指针。幸运的话,如果任何“sender”对象内存布局中包含一个0/nil字节然后NSLog()不会崩溃但输出的东西会是你完全无法想象到的,如

You tapped on: xËj

实际上,你可以看到这个来自什么地方再次运行程序点击按钮等待崩溃现在,左半边调试窗格右键单击“sender*发件人查看内存选项一定要选择一个与sender前面星号

The view memory menu option.

Xcode 会告诉你在内存中的具体内容,我们看到在某个位置有00,之前的内容就是  NSLog() 所输出的


Xcode shows the contents of memory.

然而,不能保证一定有一个NUL字节可以很容易地运行EXC_BAD_ACCESS错误如果你总是测试你的应用程序在模拟器上可能不会发生很长一段时间,一般情况下,可能在您的特定测试环境中运行总是你的青睐这使得这些类型的错误非常难以追查
当然在这种情况下的Xcode已经警告在错误格式规范,所以这个特定的错误很容易找到每当你使用C字符串直接操纵内存,你必须非常小心,不要破坏周围的内存区块
如果你够幸运的应用程序将始终崩溃错误很容易找到但更常见的,应用程序有时只会崩溃 - 使问题难以重现 - 然后追捕错误可以采取难遇

很容易fix这个问题,采用%@,当然最后还是要明确适用类型,例如@f 给float。%i给int

NSLog(@"You tapped on: %@", sender);

运行程序后,发现还是会出错哦,下回再分析:

2012-04-14 21:13:34.395 Problems[1297:f803] You tapped on: <UIRoundedRectButton: 0x6866200; frame = (119 189; 82 37); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x68662d0>>


译者总结:

1.还是不要忽视任何告警

2.基本的调试是通用的(windows/mac),看内存, 看布局,看特殊的字符?有没有pageheap/stack overfollow之类的检查?


原创粉丝点击