﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-佳为好友-随笔分类-Debug</title><link>http://www.cppblog.com/walkklookk/category/17758.html</link><description /><language>zh-cn</language><lastBuildDate>Wed, 30 Nov 2011 09:09:55 GMT</lastBuildDate><pubDate>Wed, 30 Nov 2011 09:09:55 GMT</pubDate><ttl>60</ttl><item><title>mmmmm</title><link>http://www.cppblog.com/walkklookk/archive/2011/11/17/160357.html</link><dc:creator>佳为好友</dc:creator><author>佳为好友</author><pubDate>Thu, 17 Nov 2011 08:52:00 GMT</pubDate><guid>http://www.cppblog.com/walkklookk/archive/2011/11/17/160357.html</guid><description><![CDATA[nnnnn<img src ="http://www.cppblog.com/walkklookk/aggbug/160357.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/walkklookk/" target="_blank">佳为好友</a> 2011-11-17 16:52 <a href="http://www.cppblog.com/walkklookk/archive/2011/11/17/160357.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>检查内存泄露的思路</title><link>http://www.cppblog.com/walkklookk/archive/2011/10/10/157960.html</link><dc:creator>佳为好友</dc:creator><author>佳为好友</author><pubDate>Mon, 10 Oct 2011 06:06:00 GMT</pubDate><guid>http://www.cppblog.com/walkklookk/archive/2011/10/10/157960.html</guid><wfw:comment>http://www.cppblog.com/walkklookk/comments/157960.html</wfw:comment><comments>http://www.cppblog.com/walkklookk/archive/2011/10/10/157960.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/walkklookk/comments/commentRss/157960.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/walkklookk/services/trackbacks/157960.html</trackback:ping><description><![CDATA[创建：Monday, October 10, 2011<br /><br />首先，使用XCode的静态解析工具，尽量去掉内存泄露的地方。<br />然后，使用Leaks工具找到内存泄露的对象。记得选择Leaks，并去掉每10s的自动解析功能，要手动解析，因为这样运行起来会比较快。<br />按照先易后难的方法解决每个Leak，有时候你会发现，那些比较难的Leak，会随着简单的Leak的解决而消失。<br />结合Zombies来解决Leaks。<br /><br />比较复杂的Leaks：<br />Leak发生在系统函数中。<br />随机的Leak。<br />只有真机才出现的Leak。无法使用Zombies。<br />程序太大了，导致无法使用Leaks程序解析。<br /><br /><br /><br />＋＋＋＋＋<img src ="http://www.cppblog.com/walkklookk/aggbug/157960.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/walkklookk/" target="_blank">佳为好友</a> 2011-10-10 14:06 <a href="http://www.cppblog.com/walkklookk/archive/2011/10/10/157960.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>利用Leaks和Zombies检查内存泄露</title><link>http://www.cppblog.com/walkklookk/archive/2011/10/10/157959.html</link><dc:creator>佳为好友</dc:creator><author>佳为好友</author><pubDate>Mon, 10 Oct 2011 05:58:00 GMT</pubDate><guid>http://www.cppblog.com/walkklookk/archive/2011/10/10/157959.html</guid><wfw:comment>http://www.cppblog.com/walkklookk/comments/157959.html</wfw:comment><comments>http://www.cppblog.com/walkklookk/archive/2011/10/10/157959.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/walkklookk/comments/commentRss/157959.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/walkklookk/services/trackbacks/157959.html</trackback:ping><description><![CDATA[创建：Monday, October 10, 2011<br />修改：Friday, October 28, 2011<br /><br /><span style="background-color: yellow; ">本文无效。</span><span style="background-color: yellow; ">Leaks可以直接查看</span><span style="background-color: yellow; ">retain和release的历史。</span><br /><br />Leaks只能知道哪个类进行了泄露，以及它是在什么地方分配的。但是，却无法知道是在什么地方泄露的，也就是说无法知道全部的retain和release的历史。但是，Zombies却知道，因此可以结合两者。<br /><br />方法如下：<br /><br />用Leaks找到内存泄露的类。<br />找到该对象的分配地址。<br />利用TTT类延迟10s释放该对象，释放多次，确保一定Crash。<br />然后使用Zombies运行程序。<br />当程序因为TTT崩溃时，查看retain／release的历史。检查在什么地方两者不匹配了。<br /><br />使用此方法普通的泄露问题都可以解决。<br /><br />此外，TTT类是另一篇文章里面的类。用于结合Zombies类查看对象的retain和release的历史的。<br />＋＋＋＋＋<img src ="http://www.cppblog.com/walkklookk/aggbug/157959.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/walkklookk/" target="_blank">佳为好友</a> 2011-10-10 13:58 <a href="http://www.cppblog.com/walkklookk/archive/2011/10/10/157959.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>查看retain和release的历史记录</title><link>http://www.cppblog.com/walkklookk/archive/2011/10/06/157658.html</link><dc:creator>佳为好友</dc:creator><author>佳为好友</author><pubDate>Thu, 06 Oct 2011 13:43:00 GMT</pubDate><guid>http://www.cppblog.com/walkklookk/archive/2011/10/06/157658.html</guid><wfw:comment>http://www.cppblog.com/walkklookk/comments/157658.html</wfw:comment><comments>http://www.cppblog.com/walkklookk/archive/2011/10/06/157658.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/walkklookk/comments/commentRss/157658.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/walkklookk/services/trackbacks/157658.html</trackback:ping><description><![CDATA[创建：Thursday, October 06, 2011<br />修改：Thursday, November 03, 2011：增加循环引用的检测。<br /><br /><br /><br />malloc_history只能查看alloc和dealloc的历史，看不到retain和release的历史，但是Instruments却可以，我们可以利用之。<br /><br />思路是：对想查看的对象进行过度的release，这样就可以利用Instruments来查看了。<br /><br />简单的方法如下：<br /><br /><div style="font-size: 13px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-right: 5px; padding-bottom: 4px; padding-left: 4px; padding-top: 4px; width: 98%; word-break: break-all; background-color: #eeeeee; "><span style="color: #000000; "><div>        <p>static id sNeedReleaseObj = nil;</p> <p><br /></p> <p>@interface TTT : NSObject</p> <p><br /></p> <p>- (void)releaseUntilCrash;</p> <p><br /></p> <p>@end</p> <p><br /></p> <p>@implementation TTT</p> <p>- (void)delayReleaseUntilCrash</p> <p>{</p> <p>&nbsp; &nbsp; if (sNeedReleaseObj == nil) {</p> <p>&nbsp; &nbsp; &nbsp; &nbsp; return;</p> <p>&nbsp; &nbsp; }</p> <p>&nbsp; &nbsp; for (int pos=0; pos&lt;10000; pos++) {</p> <p>&nbsp; &nbsp; &nbsp; &nbsp; [sNeedReleaseObj release];</p> <p>&nbsp; &nbsp; } &nbsp; &nbsp;</p> <p>}</p> <p><br /></p> <p>- (void)releaseUntilCrash</p> <p>{</p> <p>&nbsp; &nbsp; [self performSelector:@selector(delayReleaseUntilCrash) withObject:nil afterDelay:10.0f];</p> <p>}</p> <p>@end</p></div></span></div><br />调用的时候，可以用：<br /><br /><div style="background-color: #eeeeee; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-right: 5px; padding-bottom: 4px; padding-left: 4px; padding-top: 4px; width: 98%; word-break: break-all; font-size: 13px; "><span style="color: #000000; "><div>        <p>&nbsp;</p><div><div>&nbsp; &nbsp; &nbsp; &nbsp; TTT *ttt = [[TTT alloc] init];</div><div>&nbsp; &nbsp; &nbsp; &nbsp; sNeedReleaseObj = csvDict;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; [ttt performSelectorOnMainThread:@selector(releaseUntilCrash) withObject:nil waitUntilDone:NO];</div></div><p>&nbsp;</p></div></span></div><br /><br /><div>csvDict一定会Crash的，然后就可以查看csvDict的retain和release历史记录了。</div><br /><br />＝＝＝＝＝<br />对于循环引用，也就是A强引用B，B有强引用A，导致AB都无法释放的问题。例如：<br /><div style="font-size: 13px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-right: 5px; padding-bottom: 4px; padding-left: 4px; padding-top: 4px; width: 98%; word-break: break-all; background-color: #eeeeee; "><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->-&nbsp;(IBAction)onBtnPressed:(id)sender&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;A&nbsp;*a&nbsp;=&nbsp;[[A&nbsp;alloc]&nbsp;init];<br />&nbsp;&nbsp;&nbsp;&nbsp;B&nbsp;*b&nbsp;=&nbsp;[[B&nbsp;alloc]&nbsp;init];<br />&nbsp;&nbsp;&nbsp;&nbsp;a.b&nbsp;=&nbsp;b;<br />&nbsp;&nbsp;&nbsp;&nbsp;b.a&nbsp;=&nbsp;a;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;[a&nbsp;release];<br />&nbsp;&nbsp;&nbsp;&nbsp;[b&nbsp;release];<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;TTT&nbsp;*ttt&nbsp;=&nbsp;[[TTT&nbsp;alloc]&nbsp;init];<br />&nbsp;&nbsp;&nbsp;&nbsp;sNeedReleaseObj&nbsp;=&nbsp;a;<br />&nbsp;&nbsp;&nbsp;&nbsp;[ttt&nbsp;performSelectorOnMainThread:@selector(releaseUntilCrash)&nbsp;withObject:nil&nbsp;waitUntilDone:NO];<br /><br />}</div><br />如果不加入TTT，则上面的代码中，A和B都无法释放。<br />加入TTT之后，查看Instruments的结果如下：<br /><img src="http://www.cppblog.com/images/cppblog_com/walkklookk/LoopRef.png" width="940" height="143" alt="循环引用释放时的状态图" /><br /><br />注意：在倒数2次TTT的调用中间，会有一次-[B dealloc]，这在正常释放的情况下是不存在的，只有发生了双重引用才会出现这个问题。这说明在A和B循环引用了。因为，TTT释放的是A，而上述图例中出现了B，因此说明A和B循环引用了，这样就可以直接确定循环引用的2个对象了。<br />循环引用是很难发现的，因为它即不是内存泄露，也不会出现内存崩溃，只是始终霸占着内存不释放。只有通过Instruments的Allocations，才能大约判断是哪个对象没有正确释放，然后在使用TTT来查找出来。<br /><br />＋＋＋＋＋<img src ="http://www.cppblog.com/walkklookk/aggbug/157658.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/walkklookk/" target="_blank">佳为好友</a> 2011-10-06 21:43 <a href="http://www.cppblog.com/walkklookk/archive/2011/10/06/157658.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用Crash文件的步骤和原理</title><link>http://www.cppblog.com/walkklookk/archive/2011/09/30/157202.html</link><dc:creator>佳为好友</dc:creator><author>佳为好友</author><pubDate>Fri, 30 Sep 2011 01:48:00 GMT</pubDate><guid>http://www.cppblog.com/walkklookk/archive/2011/09/30/157202.html</guid><wfw:comment>http://www.cppblog.com/walkklookk/comments/157202.html</wfw:comment><comments>http://www.cppblog.com/walkklookk/archive/2011/09/30/157202.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/walkklookk/comments/commentRss/157202.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/walkklookk/services/trackbacks/157202.html</trackback:ping><description><![CDATA[创建：2011.06.22<br /><br />使用Crash文件的步骤：<br />＃注意：XCode4通常不能找到正确的dSYM文件。解决方法是，为Spotlight加入两个忽略的文件路径。<br />~/Library/Developer/Xcode/DerivedData/<br />~/Library/Application Support/iPhone Simulator/<br />参见文章&#8220;The symbolicator helps those who help themselves&#8221;<br />地址：<a class="moz-txt-link-freetext" title="http://www.goosoftware.co.uk/blog/the-symbolicator-helps-those" href="http://www.goosoftware.co.uk/blog/the-symbolicator-helps-those">http://www.goosoftware.co.uk/blog/the-symbolicator-helps-those</a>- who-help-themselves/<br />＃源代码上传并tag一个版本。<br />＃生成AdHoc包。Release或者Debug都可以。<br />＃生成xcarchive文件。保存该文件到某个你习惯的路径。<br />＃得到ipa包。<br />＃发布到手机。<br />＃产生异常。<br />＃连接手机和mac。<br />＃在CrashLog中得到Crash的log。<br />＃查看log的信息。<br />＃在源代码中对应。<br /><br />一些原理：<br />XCode的解析本质上是使用symbolicatecrash来解析的。输出结果是完全一样的。<br /><br />如果发现XCode解析不对了，那么可以手动调用symbolicatecrash来进行解析，看看在什么地方出现了错误。例如：<br />/Developer432/Platforms/iPhoneOS.platform/Developer/Library/PrivateFrameworks/DTDeviceKit.framework/Versions/A/Resources/symbolicatecrash -v /Users/chenjiasi/Library/Logs/CrashReporter/MobileDevice/iPhone4/MyTestPlayer_2011-06-22-141220_iPhone4.crash&nbsp;&nbsp; &gt; test.txt<br />注意，其中有个－v的选项。<br />上述命令，在test.txt中会保存解析后Crash文件的内容。而终端上会保存详细信息。<br />通常要查看终端的内容，搜索dSYM，看看得到dSYM是不是正确的。<br /><br />终端的Log记录了symbolicatecrash的过程，参照：<br />＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊<br />.........fetching symbol file for MyTestCrash--[undef] <br />Searching []...-- NO MATCH<br />Searching in Spotlight for dsym with UUID of b2026236f93c3520933c4373db77114f<br />Running mdfind "com_apple_xcode_dsym_uuids == B2026236-F93C-3520-933C-4373DB77114F"<br />Running mdls -name com_apple_xcode_dsym_paths \/Users\/chenjiasi\/tttt\/3\/MyTestCrash\ 11\-6\-22\ \?\?\?\?\?\?2\.45\.xcarchive<br />Running mdls -name com_apple_xcode_dsym_paths \/Users\/chenjiasi\/tttt\/2\/MyTestCrash\ 11\-6\-22\ \?\?\?\?\?\?2\.45\.xcarchive<br />Running mdls -name com_apple_xcode_dsym_paths \/Users\/chenjiasi\/tttt\/1\/MyTestCrash\ 11\-6\-22\ \?\?\?\?\?\?2\.45\.xcarchive<br />Running mdls -name com_apple_xcode_dsym_paths \/Users\/chenjiasi\/Library\/Developer\/Xcode\/Archives\/2011\-06\-22\/MyTestCrash\ 11\-6\-22\ \?\?\?\?\?\?2\.45\.xcarchive<br />@dsym_paths = ( /Users/chenjiasi/tttt/3/MyTestCrash 11-6-22 下午2.45.xcarchive/dSYMs/MyTestCrash.app.dSYM/Contents/Resources/DWARF /MyTestCrash /Users/chenjiasi/tttt/2/MyTestCrash 11-6-22 下午2.45.xcarchive/dSYMs/MyTestCrash.app.dSYM/Contents/Resources/DWARF /MyTestCrash /Users/chenjiasi/tttt/1/MyTestCrash 11-6-22 下午2.45.xcarchive/dSYMs/MyTestCrash.app.dSYM/Contents/Resources/DWARF /MyTestCrash /Users/chenjiasi/Library/Developer/Xcode/Archives/2011-06-22/MyTestCrash 11-6-22 下午2.45.xcarchive/dSYMs/MyTestCrash.app.dSYM/Contents/Resources/DWARF /MyTestCrash )<br />@exec_names = ( MyTestCrash )<br />Running mdfind "kMDItemContentType == com.apple.application-bundle &amp;&amp; kMDItemFSName == MyTestCrash.app"<br />Running find "/Users/chenjiasi/tttt/3/MyTestCrash 11-6-22 下午2.45.xcarchive/Products" -name MyTestCrash.app<br />Running find "/Users/chenjiasi/tttt/2/MyTestCrash 11-6-22 下午2.45.xcarchive/Products" -name MyTestCrash.app<br />Running find "/Users/chenjiasi/tttt/1/MyTestCrash 11-6-22 下午2.45.xcarchive/Products" -name MyTestCrash.app<br />Running find "/Users/chenjiasi/Library/Developer/Xcode/Archives/2011-06-22/MyTestCrash 11-6-22 下午2.45.xcarchive/Products" -name MyTestCrash.app<br />Running \/Developer432\/Platforms\/iPhoneOS\.platform\/Developer\/usr\/bin\/otool -arch armv7 -l '/Users/chenjiasi/tttt/2/MyTestCrash 11-6-22 下午2.45.xcarchive/Products/Applications/MyTestCrash.app/MyTestCrash'<br /><br />Number of symbols in /Users/chenjiasi/tttt/2/MyTestCrash 11-6-22 下午2.45.xcarchive/Products/Applications/MyTestCrash.app/MyTestCrash: 1 + 1 = 2<br />Found executable /Users/chenjiasi/tttt/2/MyTestCrash 11-6-22 下午2.45.xcarchive/Products/Applications/MyTestCrash.app/MyTestCrash<br />-- MATCH<br />＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊<br />纵观全局，系统先通过UUID查找dSYM，在通过dSYM，然后查找对应的App。<br />查找dSYM使用确定的UUID查找，因此理论上不会找错。（PS：但是，实际上却不一定，有找错的可能。）<br /><br />通过Log中：&#8220;Searching in Spotlight for dsym with UUID of b2026236f93c3520933c4373db77114f&#8221;可以判断出来，系统使用的是Spotlight来查找dSYM的。<br /><br />查看-- MATCH前的内容，可以确定系统使用哪个文件进行符号解析的。本例中使用了/Users/chenjiasi/tttt/2/MyTestCrash 11-6-22 下午2.45.xcarchive/Products/Applications/MyTestCrash.app/MyTestCrash<br /><br />也可以查看otool命令中的参数的内容来确定。<br /><br />源文件删除了不要紧。解析不依赖于源文件。都放到dSYM或App中了。<br />dSYM和App都是需要的，但是在XCode4生成的xcarchive文件中都全部包括了。<br /><br />注意：如果没有找到dSYM，则其它framework的内容也会解析出来，但是App的内容就无法解析了。<br />注意：直接调试发布到手机上的程序，解析出来的内容不对，好像是因为dSYM不对的缘故。因此，必须使用AdHoc包才行。<br />注意：只要是AdHoc包就可以。无论是从Debug还是Release得到的。好像是因为Entitlements.plist里面的 Can be debugged属性决定的。<br />注意：有的文章上写出在symbolicatecrash命令后面加入dSYM来指定特定的dSYM，但是经过我的测试，这是不起任何作用 的。symbolicatecrash还是会搜索并选择第一个合适的dSYM。<br /><br />程序崩溃之后，会产生一个crash文件和一个plist文件。两者内容相同，格式不同。其中，前者是为XCode使用的。后者不清楚用途。<br />Crash文件在XCode解析出来后，会单独另外生成一个Crash文件，该文件通常已经包含了解析后的内容。<br />如果需要手动调试symbolicatecrash，注意选择那个没有生成调试符号的。<br /><br />通过其它文章，我们可以推断出symbolicatecrash得到app也应该是通过UUID的。而且app的UUID和dSYM的 UUID是同一个。可以这样查看：<br />pics&#8208;imac:Downloads pic$ dwarfdump &#8208;&#8208;uuid MyApp.app/MyApp&nbsp;&nbsp;&nbsp;&nbsp; [自：注意，这里不是.app文件夹，而是在.app下的可执行文件]<br /><br />UUID: E2D9D241&#8208;37D3&#8208;CE06&#8208;7272&#8208;653B813963E2 (armv6) MyApp.app/MyApp<br /><br />Now we run the same command on our .dSYM file and get this result:<br /><br />pics&#8208;imac:Downloads pic$ dwarfdump &#8208;&#8208;uuid MyApp.app.dSYM<br />UUID: E2D9D241&#8208;37D3&#8208;CE06&#8208;7272&#8208;653B813963E2 (armv6)<br />MyApp.app.dSYM/Contents/Resources/DWARF/MyApp<br />参照：<a class="moz-txt-link-freetext" title="http://www.picsoftware.ca/blog/?p=8" href="http://www.picsoftware.ca/blog/?p=8">http://www.picsoftware.ca/blog/?p=8</a><br /><br /><br /><br />几个地址：<br />XCode4的symbolicatecrash的地址：/Developer/Platforms/iPhoneOS.platform /Developer/Library/PrivateFrameworks/DTDeviceKit.framework/Versions/A/Resources/symbolicatecrash<br /><br /><br />+++++<br /><img src ="http://www.cppblog.com/walkklookk/aggbug/157202.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/walkklookk/" target="_blank">佳为好友</a> 2011-09-30 09:48 <a href="http://www.cppblog.com/walkklookk/archive/2011/09/30/157202.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转：关于重定向stderr到文件 NSLog</title><link>http://www.cppblog.com/walkklookk/archive/2011/09/21/156415.html</link><dc:creator>佳为好友</dc:creator><author>佳为好友</author><pubDate>Wed, 21 Sep 2011 06:14:00 GMT</pubDate><guid>http://www.cppblog.com/walkklookk/archive/2011/09/21/156415.html</guid><wfw:comment>http://www.cppblog.com/walkklookk/comments/156415.html</wfw:comment><comments>http://www.cppblog.com/walkklookk/archive/2011/09/21/156415.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/walkklookk/comments/commentRss/156415.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/walkklookk/services/trackbacks/156415.html</trackback:ping><description><![CDATA[转：<a title="http://www.cocoachina.com/bbs/read.php?tid-39344.html" href="http://www.cocoachina.com/bbs/read.php?tid-39344.html">http://www.cocoachina.com/bbs/read.php?tid-39344.html</a><br /><br /><span style="color: rgb(0,0,153)">[自:我在iOS4.2 Debug和Relase版本的模拟器上的试验结果是：</span><br style="color: rgb(0,0,153)" /><span style="color: rgb(0,0,153)">使用NSLog的话，即使不使用fflush(stderr)，也会立刻更新到文件中的。</span><br style="color: rgb(0,0,153)" /><span style="color: rgb(0,0,153)">使用fprintf(stderr, "hello\n");的话，默认不会立刻更新到文件中。</span><br style="color: rgb(0,0,153)" /><span style="color: rgb(0,0,153)">但是如果调用fflush(stderr)，则会立刻更新到文件中。这一点跟楼主的试验结果不同啊。会不会是iOS的版本不同导致的。 ]</span><br /><br /><font size="4">你可能会碰到某些情况下你无法用xcode进行调试，或者用GDB查看NSLog的输出，比如你正在为某个外部附件<span style="border-bottom: rgb(250,137,27) 1px solid; cursor: pointer" id="rlt_1">开发</span><span style="border-bottom: rgb(250,137,27) 1px solid; cursor: pointer" id="rlt_5">应用</span>程序。<br />没有Log是对于<span style="border-bottom: rgb(250,137,27) 1px solid; cursor: pointer" id="rlt_7">定位</span>和查找bug都是非常困难的，好在我们可以通过重定向，将标准的<span style="border-bottom: rgb(250,137,27) 1px solid; cursor: pointer" id="rlt_8">错误</span>输出stderr定向到文件。<br />这里我只是<span style="border-bottom: rgb(250,137,27) 1px solid; cursor: pointer" id="rlt_6">分享</span>给大家一些调试的经验和方法。请大大们轻拍。<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;NSArray *paths = NSSearchPathForDirectoriesInDomains(<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NSDocumentDirectory, NSUserDomainMask, YES);<br />&nbsp;&nbsp;&nbsp;&nbsp;NSString *documentDir = [paths objectAtIndex:0];<br />&nbsp;&nbsp;&nbsp;&nbsp;NSString *logPath = [documentDir stringByAppendingPathComponent:@"decrypt.log"];<br />&nbsp;&nbsp;&nbsp;&nbsp;freopen([logPath cStringUsingEncoding:NSASCIIStringEncoding], "w+", stderr);<br /><br />让我们看下这段<span style="border-bottom: rgb(250,137,27) 1px solid; cursor: pointer" id="rlt_2">代码</span>，它的作用就是在程序内部的文件夹Documents中新建一个名为decrypt.log的文件，并且将所有的stderr输入到decrypt.log<br />文件中。如此一来所有关于stderr的输出都将被重定向到decrypt.log，在gdb中你将无法再看到这些信息。<br /><br />关于<span style="border-bottom: rgb(250,137,27) 1px solid; cursor: pointer" id="rlt_3">使用</span>：<br />下面来说说如何查看这个文件（可能很多同学都会了）<br />1、xcode-&gt;Windows-&gt;Organizer <br />2、找到你的设备，在summary一栏中找到你的程序，将其展开，点选右边那个小箭头，这样程序内部的所有文件夹都将导出到你所指定的位置。<br />3、还是Organizer左边一栏的PROJECTS&amp;SOURCES展开便能找到<br /><br /><br />关于 printf, fprintf 和NSLog：<br />可能你大量使用了外部的c库，它们以printf或者fprintf来输出信息 ，那么它们的区别又是什么？<br />标准的printf它是将调试信息<span style="border-bottom: rgb(250,137,27) 1px solid; cursor: pointer" id="rlt_4">输入</span>到标准输出流stdout，也就是说你用上面提供的函数是无法将此重定向的，你必须<br />reopen([logPath cStringUsingEncoding:NSASCIIStringEncoding], "w+", stdout);<br />而fprintf则可以指定你所要输出的调试信息的位置，包括stdout、stderr甚至是一般的文件。<br />这里我们输出到stderr <br />fprintf(stderr, "hello\n");<br /><br />NSLog它本质上其实也是将调试信息输出到stderr（并不确定？），但与fprintf不同它还有些不一样的特性。<br /><br />我们在使用xcode进行调试的时候无论采用哪种方式输出错误信息总是第一时间刷新在屏幕上，但定向到文件却有所不同，<br />NSLog总是能第一时间写到文件，而printf或者fprintf它们似乎将是信息保存在缓存中，等待某种契机或者信号才会将<br />信息写到文件中如此一来辛苦准备的调试信息却可能因为程序的崩溃而什么也无法看到。<br />所以我们可以通过fflush来强制它进行刷新。如下，我们强制刷新stderr<br />fflush(stderr)<br /><br />但是这里我有一个疑问，想请各位高手指教，我实验中我发现NSLog确实应该是stderr的输出流，那么按照我上面所说的，<br />为了保证信息的即时输出，它应该内部调用了fflush(stderr)才对，但是如果是fflush(stderr)的话，那么之前的stderr上的信息应该也是<br />一起输出的，但结果却是只有NSLog的信息得到了输出，原本stderr中的信息依旧保存在缓存中，不知道NSLog到底做了<br />些什么。。。<br /><br />最后给大家两个调试用的宏（可能各位也早已知道）<br />__FILE__&nbsp;&nbsp;分别是所在的文件 （字符串）<br />__LINE__&nbsp;&nbsp;和行号（数字）<br />希望对大家有所帮助</font><br />＋＋＋＋＋<br /><img src ="http://www.cppblog.com/walkklookk/aggbug/156415.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/walkklookk/" target="_blank">佳为好友</a> 2011-09-21 14:14 <a href="http://www.cppblog.com/walkklookk/archive/2011/09/21/156415.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>XCode调试经验</title><link>http://www.cppblog.com/walkklookk/archive/2011/09/21/156411.html</link><dc:creator>佳为好友</dc:creator><author>佳为好友</author><pubDate>Wed, 21 Sep 2011 06:08:00 GMT</pubDate><guid>http://www.cppblog.com/walkklookk/archive/2011/09/21/156411.html</guid><wfw:comment>http://www.cppblog.com/walkklookk/comments/156411.html</wfw:comment><comments>http://www.cppblog.com/walkklookk/archive/2011/09/21/156411.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/walkklookk/comments/commentRss/156411.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/walkklookk/services/trackbacks/156411.html</trackback:ping><description><![CDATA[创建:2010-03-29<br /><br />*在GDB使用断点命令时,要注意,在p的前面加入一个空格.这个可能是跟XCode的dbg窗口有关的.<br />因为在这个dbg窗口中,每个命令之前都是有一个空格的,在这个空格中是无法输入字的.但是在<br />commands命令中,如果你不加入这个空格,则无法正确识别后面的命令,如果加入空格则一切都正常.<br /><br />*在XCode的BreakPoints中,使用Log的@@中加入dbg命令不不是很好用,建议还是使用Command类型,这个比较容易成功.<br /><br /><br /><img src ="http://www.cppblog.com/walkklookk/aggbug/156411.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/walkklookk/" target="_blank">佳为好友</a> 2011-09-21 14:08 <a href="http://www.cppblog.com/walkklookk/archive/2011/09/21/156411.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转：Leaks程序的工作原理</title><link>http://www.cppblog.com/walkklookk/archive/2011/09/19/156210.html</link><dc:creator>佳为好友</dc:creator><author>佳为好友</author><pubDate>Mon, 19 Sep 2011 05:14:00 GMT</pubDate><guid>http://www.cppblog.com/walkklookk/archive/2011/09/19/156210.html</guid><wfw:comment>http://www.cppblog.com/walkklookk/comments/156210.html</wfw:comment><comments>http://www.cppblog.com/walkklookk/archive/2011/09/19/156210.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/walkklookk/comments/commentRss/156210.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/walkklookk/services/trackbacks/156210.html</trackback:ping><description><![CDATA[转：09/19/2011<br /><br />转：http://www.cocoadev.com/index.pl?HowToFindMemoryLeaks<br /><p>
Some tips and threaded discussion about using such tools as the <em>leaks</em> program and links to other <a href="http://www.cocoadev.com/index.pl?DeveloperTools">DeveloperTools</a> for the purpose at hand:
</p><p>
</p><ul><p>
</p><li> Expand the disclosure triangle beside "Executables" in <a href="http://www.cocoadev.com/index.pl?XCode">XCode</a>
 and highlight your executable (In Xcode 2.5, double-click the 
executable and select the "Arguments" tab in the Info window. Be sure to
 add environment variables, not arguments.)
</li><li> The right pane shows the arguments you can pass your 
application at runtime.  Click the + below Environment Variables.  The 
new Name should be <a href="http://www.cocoadev.com/index.pl?MallocStackLogging">MallocStackLogging</a> and the Value should be YES. Add an environment variable for MallocStackLoggingNoCompact<a href="http://www.cocoadev.com/index.pl?edit=MallocStackLoggingNoCompact">?</a>=YES as well.
</li><li> Compile and run your application
</li><li> open terminal and run "ps ax | grep -i yourappname
</li><li> The first column in the row for your app is its Process ID (pid).  Make a mental note of it.
</li><li> <span style="background-color: #ff99cc;">type "leaks pid|more" in the terminal, where pid is the number of the Process ID
</span></li><li> You will get about a paragraph of information for each memory 
leak.  The first line will usually give you the class name of the object
 that is being leaked.  Make a note of it.
</li><li> Using enter or spacebar to scroll, scroll down to the end of 
the entry, where you will see a series of Objective-C class and method 
calls all jammed together.  Somewhere in the last 5 to 10 method calls 
you can usually spot the name of a method you wrote in a class you wrote
 or subclassed.
</li><li> Examine that method in <a href="http://www.cocoadev.com/index.pl?XCode">XCode</a>.
</li><li> see <a href="http://www.cocoadev.com/index.pl?RetainReleaseTips">RetainReleaseTips</a> for information on how to manage memory.  The basic rule is: If you alloc, retain or copy it, you need to release it.
</li><li> exercise the functionality of your app, checking back on leaks occasionally to see if it is leaking memory.
</li><li> When you get all the memory leaks out the leaks command should return 0 leaks.
</li><li>In addition to Leaks, there are <a href="http://www.cocoadev.com/index.pl?ObjectAlloc">ObjectAlloc</a> and <a href="http://www.cocoadev.com/index.pl?OmniObjectMeter">OmniObjectMeter</a>.
<p>
</p></li></ul>
<p>
NOTE: You should make sure you do not run leaks with <a href="http://www.cocoadev.com/index.pl?NSZombieEnabled">NSZombieEnabled</a> or it will look like everything is leaking!
</p><p>
-- <a href="http://www.cocoadev.com/index.pl?TKinch">TKinch</a>
</p><br /><br />＋＋＋＋＋<img src ="http://www.cppblog.com/walkklookk/aggbug/156210.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/walkklookk/" target="_blank">佳为好友</a> 2011-09-19 13:14 <a href="http://www.cppblog.com/walkklookk/archive/2011/09/19/156210.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转：[objc explain]: So you crashed in objc_msgSend()</title><link>http://www.cppblog.com/walkklookk/archive/2011/09/19/156190.html</link><dc:creator>佳为好友</dc:creator><author>佳为好友</author><pubDate>Mon, 19 Sep 2011 03:21:00 GMT</pubDate><guid>http://www.cppblog.com/walkklookk/archive/2011/09/19/156190.html</guid><wfw:comment>http://www.cppblog.com/walkklookk/comments/156190.html</wfw:comment><comments>http://www.cppblog.com/walkklookk/archive/2011/09/19/156190.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/walkklookk/comments/commentRss/156190.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/walkklookk/services/trackbacks/156190.html</trackback:ping><description><![CDATA[转：09/18/2011<br /><br />转：http://www.sealiesoftware.com/blog/archive/2008/09/22/objc_explain_So_you_crashed_in_objc_msgSend.html<br /><br /><p>
	So you crashed in <code>objc_msgSend()</code>. Now what?
      </p>
      <p>
	Most likely, you sent a message to an already-freed
	object. Or maybe your pointer is perfectly correct, but
	someone else mangled the object's contents - perhaps a buffer
	overrun in a nearby allocation, or use of a dangling pointer that once
	pointed to the memory now occupied by your object. Occasionally
	<code>objc_msgSend()</code> crashes because a memory error smashed
	the runtime's own data structures, but usually the trouble is in
	the receiver object itself.
      </p>
      <p>
	Whether you're in the debugger or looking at a crash log, you can
	recover more information about the crash than just the backtrace. 
      </p>
      <h4>Receiver and selector registers</h4>
      <p>
	<code>objc_msgSend()</code> stores the receiver object and the
	selector in CPU registers while it works. These values can help 
	diagnose the problem.
      </p>
      <p>
	The register names differ based on architecture and the 
	<code>objc_msgSend()</code> variant used. This list is correct for
	Mac OS X Leopard and will probably remain correct for Snow
	Leopard. 
	</p><table border="1" cellpadding="4" cellspacing="0">
	  <tbody><tr><th><br /></th><td colspan="2" align="center"><code>objc_msgSend</code><br /><code>objc_msgSend_fpret</code></td>
	    <td colspan="2" align="center"><code>objc_msgSend_stret</code></td>
	  </tr><tr><td align="center">&nbsp;</td><td align="center"><code>receiver</code></td><td align="center"><code>SEL</code></td><td align="center"><code>receiver</code></td><td align="center"><code>SEL</code></td></tr>
	  <tr><td>i386</td><td align="center">eax*</td><td align="center">ecx</td>
	    <td align="center">eax*</td><td align="center">ecx</td></tr>
	  <tr><td>x86_64</td><td align="center">rdi</td><td align="center">rsi</td>
	    <td align="center">rsi</td><td align="center">rdx</td></tr>
	  <tr><td>ppc</td><td align="center">r3</td><td align="center">r4</td>
	    <td align="center">r4</td><td align="center">r5</td></tr>
	  <tr><td>ppc64</td><td align="center">r3</td><td align="center">r4</td>
	    <td align="center">r4</td><td align="center">r5</td></tr>
	  <tr><td>arm</td><td align="center">r0</td><td align="center">r1</td>
	    <td align="center">r1</td><td align="center">r2</td></tr>
	</tbody></table>
	* i386 note: The receiver is in eax for most crashes, but not
	all. If you manage to get far into <code>objc_msgSend()</code>
	before falling over, then eax will have some other value.
      
      <h4>Interpreting the receiver and invalid address</h4>
      <p>
	You can use the receiver's address and the invalid address that
	caused the crash to get some hints about the underlying
	problem. In a crash log, the receiver's address is in the Thread
	State using the register name in the table above, and the invalid
	address is listed at the top (usually something like
	<code>KERN_PROTECTION_FAILURE at &lt;invalid address&gt;</code>).
	In the debugger
	console, the invalid address is printed when the program stops,
	and you can print the receiver's address using the register name
	in the table above.
	</p><pre>    Program received signal EXC_BAD_ACCESS, Could not access memory.
    Reason: KERN_PROTECTION_FAILURE at address: 0x00000001
    0x00090ec4 in objc_msgSend ()
    (gdb) p/x $eax
    $1 = 0x1</pre>
	My test program crashed at <code>[(id)1 release]</code>. In real
	crashes, these values are typically more interesting.
      
      <p>
	Usually, one of two things happens. The receiver address 
	itself is bogus, and the invalid address is the same value (or 16
	or 32 bytes away). Or the receiver address is reasonable, and the
	invalid address is the receiver's <code>isa</code> pointer. The
	latter 
	is what usually happens if you try to use an already-deallocated
	object or someone else clobbered your valid object.
      </p>
      <p>
	Look for special values like these in your crashes. Also look for
	nearby values; on some architectures, an invalid <code>isa</code>
	will cause a crash at <code>isa+16</code> or <code>isa+32</code>
	instead.
	</p><dl><dt>Not divisble by 16 - misaligned</dt><dd><code>malloc()</code> returns 16-byte aligned blocks. If
	    your receiver isn't 16-byte aligned, it probably never was a
	    valid object pointer.</dd><dt>Top two and bottom two bits all set - malloc free list</dt><dd>After a block is freed, the memory allocator may write free
	    list pointers into it. If you use a freed object after this,
	    you'll see an <code>isa</code> pointer with the top two and
	    bottom two bits all set.</dd><dt>All bits inverted - GC free list</dt><dd>Like the malloc free list case above, but caused by the
	    garbage collector instead. In this case <code>address</code>
	    looks bad, but <code>~address</code> is more reasonable.</dd><dt>0xa1b1c1d3 - CF container</dt><dd>CoreFoundation containers use this value for deleted or
	    empty items. Perhaps a freed object has been re-allocated as a
	    container, or someone used a freed container that has been
	    re-allocated as your object, or you read your pointer from a
	    container that was simultaneously changed by some other thread 
	    and you don't have the right locks in place.</dd><dt>ASCII text</dt><dd>Perhaps a freed object has been re-allocated as a string, or
	    someone 
	    used a freed string that has been re-allocated as your object,
	    or some string operation has a buffer overrun. Use <a href="http://www.sealiesoftware.com/asciify.c">asciify</a> to print these quickly in both
	    endians. This one looks URL-related, for example:
	    <pre>% asciify 0x2e777777
###.www###
###www.###</pre>
	  </dd></dl>
	
      <h4>Interrogating the selector</h4>
      <p>
	Compiler optimization means the call site pointed to by the
	second frame in the backtrace might not be the call that actually 
	crashed. It's possible that call succeeded, and then that method
	made a <em>tail call</em> which was the one that crashed. Because of
	tail call optimization, the intermediate frame would be missing
	from the backtrace. We can use the selector register to determine
	what the real crashing call was.
      </p>
      <p>
	A selector is a pointer to a unique C string. This may change in
	future OS versions, but for now it's handy for debugging. If you
	have crashed in a debugger, open the debugger console and run
	this, substituting the correct <code>SEL</code> register from the
	table above:
	</p><pre>    (gdb) x/s $ecx
    0xa1029: "release"</pre>
      
      <p>
	Snow Leopard's crash reporter adds selector names to crash logs
	for you:
	</p><pre>    Application Specific Information:
    objc_msgSend() selector name: release</pre>
	Otherwise, retrieving the selector name from just a crash log is
	difficult and doesn't always work. Until you have Snow Leopard,
	cross your fingers and try this.
	<ol><li>From the crash log's Thread State, find the
	    <code>SEL</code>'s value using the register name in the table
	    above.
	    <pre>    ecx: 0x000a1029</pre>
	  </li><li>From the crash log's Binary Images, find the image whose
	    address range includes the <code>SEL</code>'s value. This will
	    often be either the application itself or <code>libobjc.A.dylib</code>. If no
	    image spans that address, give up.
	    <br /><code>&nbsp; &nbsp; 0x8b000 - &nbsp; 0x106ff7 &nbsp;libobjc.A.dylib ??? (???) &lt;9b5973b7fa88f9aab7885530c7b278dd&gt; /usr/lib/libobjc.A.dylib</code></li><li>Find a copy of the image that matches the one in the crash
	    log. Use the UUID to verify the match.
	    <pre>    % dwarfdump -u /usr/lib/libobjc.A.dylib
    UUID: 26650299-C6EA-B1C8-52D6-072AC874D400 (ppc) /usr/lib/libobjc.A.dylib
    UUID: 9B5973B7-FA88-F9AA-B788-5530C7B278DD (i386) /usr/lib/libobjc.A.dylib
    UUID: D2A4E8E1-3C1C-E0D9-2249-125B6DD621F8 (x86_64) /usr/lib/libobjc.A.dylib</pre>
	    This crash matches my installed <code>libobjc.A.dylib</code> for i386. If
	    it's a 
	    system library, you may need the image from the OS version
	    listed in the crash log. If it's your application, you did
	    keep a copy of every version you shipped, right?
	    
	  </li><li>Calculate the <code>SEL</code>'s offset into the image.
	    <pre>    0xa1029 - 0x8b000 = 0x16029</pre>
	  </li><li>Print the C string in the image at that offset. Remember to
	  specify the correct architecture.
	    <pre>    % otool -v -arch i386 -s __TEXT __cstring /usr/lib/libobjc.A.dylib | grep 16029
    00016029  release
	    </pre>
	  </li></ol><br /><br />＋＋＋＋＋<img src ="http://www.cppblog.com/walkklookk/aggbug/156190.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/walkklookk/" target="_blank">佳为好友</a> 2011-09-19 11:21 <a href="http://www.cppblog.com/walkklookk/archive/2011/09/19/156190.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>调试引用计数问题</title><link>http://www.cppblog.com/walkklookk/archive/2011/09/19/156189.html</link><dc:creator>佳为好友</dc:creator><author>佳为好友</author><pubDate>Mon, 19 Sep 2011 03:15:00 GMT</pubDate><guid>http://www.cppblog.com/walkklookk/archive/2011/09/19/156189.html</guid><wfw:comment>http://www.cppblog.com/walkklookk/comments/156189.html</wfw:comment><comments>http://www.cppblog.com/walkklookk/archive/2011/09/19/156189.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/walkklookk/comments/commentRss/156189.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/walkklookk/services/trackbacks/156189.html</trackback:ping><description><![CDATA[创建：09/18/2011<br /><br />方法一：<br />使用Instruments。<br />缺点：<br />1，无法在真机上使用。<br />2，如果数据量太大，则无法运行。<br />方法二：<br />使用如下参数：<br /><br />&nbsp; NSDebugEnabled<br />&nbsp; NSZombieEnabled<br />&nbsp; MallocStackLogging<br /><br /><br />"malloc_history &lt;pid&gt; &lt;address&gt;"<br /><br />例如：<br />(gdb) shell malloc_history 3949 0xa5e10<br /><br /><span style="background-color: #ff99cc;">注意：</span><br /><span style="background-color: #ff99cc;">NSZombieEnabled会导致MallocStackLogging不准确，因此如果确定了出问题的对象，则应该先暂时关闭NSZombieEnabled。</span><br /><br />缺点：<br />1，无法在真机使用。<br /><br /><pre>方法三：<br /><br /><br />＋＋＋＋＋<br /><br /></pre><img src ="http://www.cppblog.com/walkklookk/aggbug/156189.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/walkklookk/" target="_blank">佳为好友</a> 2011-09-19 11:15 <a href="http://www.cppblog.com/walkklookk/archive/2011/09/19/156189.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转：NSDebug.h －Cocoa的用于调试的环境变量</title><link>http://www.cppblog.com/walkklookk/archive/2011/09/17/156007.html</link><dc:creator>佳为好友</dc:creator><author>佳为好友</author><pubDate>Sat, 17 Sep 2011 02:11:00 GMT</pubDate><guid>http://www.cppblog.com/walkklookk/archive/2011/09/17/156007.html</guid><wfw:comment>http://www.cppblog.com/walkklookk/comments/156007.html</wfw:comment><comments>http://www.cppblog.com/walkklookk/archive/2011/09/17/156007.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/walkklookk/comments/commentRss/156007.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/walkklookk/services/trackbacks/156007.html</trackback:ping><description><![CDATA[转：<a title="http://theshadow.uw.hu/iPhoneSDKdoc/Foundation.framework/NSDebug.h.html" href="http://theshadow.uw.hu/iPhoneSDKdoc/Foundation.framework/NSDebug.h.html">http://theshadow.uw.hu/iPhoneSDKdoc/Foundation.framework/NSDebug.h.html</a><br /><br />
<table>
<tbody>
<tr>
<td bgcolor="#eeeeff" width="100%">
<h3>Foundation/NSDebug.h</h3></td>
<td noWrap>iPhone.SDK<br />by hackstock</td></tr></tbody></table>
<hr />
<code><font color="green">/* NSDebug.h<br />Copyright (c) 1994-2005, Apple, Inc. All rights reserved.<br />*/<br /></font><br /><font color="green">/**************************************************************************<br />WARNING: Unsupported API.<br /><br />This module contains material that is only partially supported -- if<br />at all. Do not depend on the existance of any of these symbols in your<br />code in future releases of this software. Certainly, do not depend on<br />the symbols in this header in production code. The format of any data<br />produced by the functions in this header may also change at any time.<br /><br />However, it should be noted that the features (but not necessarily the<br />exact implementation) in this file have been found to be generally useful,<br />and in some cases invaluable, and are not likely to go away anytime soon.<br />**************************************************************************/<br /></font><br />#import &lt;<a title="http://theshadow.uw.hu/iPhoneSDKdoc/Foundation.framework/NSObject.h.html" href="http://theshadow.uw.hu/iPhoneSDKdoc/Foundation.framework/NSObject.h.html">Foundation/NSObject.h</a>&gt;<br />#import &lt;<a title="http://theshadow.uw.hu/iPhoneSDKdoc/Foundation.framework/NSAutoreleasePool.h.html" href="http://theshadow.uw.hu/iPhoneSDKdoc/Foundation.framework/NSAutoreleasePool.h.html">Foundation/NSAutoreleasePool.h</a>&gt;<br />#import &lt;<a title="http://theshadow.uw.hu/iPhoneSDKdoc/Foundation.framework/NSDate.h.html" href="http://theshadow.uw.hu/iPhoneSDKdoc/Foundation.framework/NSDate.h.html">Foundation/NSDate.h</a>&gt;<br />#import &lt;<a title="http://theshadow.uw.hu/iPhoneSDKdoc/Foundation.framework/NSPort.h.html" href="http://theshadow.uw.hu/iPhoneSDKdoc/Foundation.framework/NSPort.h.html">Foundation/NSPort.h</a>&gt;<br /><br /><font color="green">/* The environment component of this API<br /><br />The boolean- and integer-valued variables declared in this header,<br />plus some values set by methods, read starting values from the<br />process's environment at process startup. This is mostly a benefit<br />if you need to initialize these variables to some non-default value<br />before your program's main() routine gets control, but it also<br />allows you to change the value without modifying your program's<br />source. (Variables can be set and methods called around specific<br />areas within a program, too, of course.)<br /><br />The initialization from the environment happens very early, but may<br />not have happened yet at the time of a +load method statically linked<br />into an application (as opposed to one in a dynamically loaded module). <br />But as noted in the "Foundation Release Notes", +load methods that are<br />statically linked into an application are tricky to use and are not<br />recommended.<br /><br />Here is a table of the variables/values initialized from the environment<br />at startup. Some of these just set variables, others call methods to<br />set the values.<br /><br />NAME OF ENV. VARIABLE DEFAULT SET TO...<br />NSDebugEnabled NO "YES"<br />NSZombieEnabled NO "YES"<br />NSDeallocateZombies NO "YES"<br />NSHangOnUncaughtException NO "YES"<br /><br />NSEnableAutoreleasePool YES "NO"<br />NSAutoreleaseFreedObjectCheckEnabled NO "YES"<br />NSAutoreleaseHighWaterMark 0 non-negative integer<br />NSAutoreleaseHighWaterResolution 0 non-negative integer<br /><br />*/<br /></font><br /><font color="green">/**************** General ****************/<br /></font><br />FOUNDATION_EXPORT BOOL NSDebugEnabled;<br /><font color="green">// General-purpose global boolean. Applications and frameworks</font><br /><font color="green">// may choose to do some extra checking, or use different</font><br /><font color="green">// algorithms, or log informational messages, or whatever, if</font><br /><font color="green">// this variable is true (ex: if (NSDebugEnabled) { ... }).</font><br /><br />FOUNDATION_EXPORT BOOL NSZombieEnabled;<br /><font color="green">// Enable object zombies. When an object is deallocated, its isa</font><br /><font color="green">// pointer is modified to be that of a "zombie" class (whether or</font><br /><font color="green">// not the storage is then freed can be controlled by the</font><br /><font color="green">// NSDeallocateZombies variable). Messages sent to the zombie</font><br /><font color="green">// object cause logged messages and can be broken on in a debugger.</font><br /><font color="green">// The default is NO.</font><br /><br />FOUNDATION_EXPORT BOOL NSDeallocateZombies;<br /><font color="green">// Determines whether the storage of objects that have been</font><br /><font color="green">// "zombified" is then freed or not. The default value (NO)</font><br /><font color="green">// is most suitable for debugging messages sent to zombie</font><br /><font color="green">// objects. And since the memory is never freed, storage</font><br /><font color="green">// allocated to an object will never be reused, either (which</font><br /><font color="green">// is sometimes useful otherwise).</font><br /><br />FOUNDATION_EXPORT BOOL NSHangOnUncaughtException;<br /><font color="green">// If set to YES, causes the process to hang after logging the</font><br /><font color="green">// "*** Uncaught exception:" message. A backtrace can be gotten</font><br /><font color="green">// from the process with the 'sample' utility, or the process can</font><br /><font color="green">// be attached to with a debugger. The default is NO.</font><br /><br />FOUNDATION_EXPORT BOOL NSIsFreedObject(id anObject);<br /><font color="green">// Returns YES if the value passed as the parameter is a pointer</font><br /><font color="green">// to a freed object. Note that memory allocation packages will</font><br /><font color="green">// eventually reuse freed memory blocks to satisfy a request.</font><br /><font color="green">// NSZombieEnabled and NSDeallocateZombies can be used to prevent</font><br /><font color="green">// reuse of allocated objects.</font><br /><br /><font color="green">/**************** Stack processing ****************/<br /></font><br />FOUNDATION_EXPORT void *NSFrameAddress(unsigned frame);<br />FOUNDATION_EXPORT void *NSReturnAddress(unsigned frame);<br /><font color="green">// Returns the value of the frame pointer or return address,</font><br /><font color="green">// respectively, of the specified frame. Frames are numbered</font><br /><font color="green">// sequentially, with the "current" frame being zero, the</font><br /><font color="green">// previous frame being 1, etc. The current frame is the</font><br /><font color="green">// frame in which either of these functions is called. For</font><br /><font color="green">// example, NSReturnAddress(0) returns an address near where</font><br /><font color="green">// this function was called, NSReturnAddress(1) returns the</font><br /><font color="green">// address to which control will return when current frame</font><br /><font color="green">// exits, etc. If the requested frame does not exist, then</font><br /><font color="green">// NULL is returned. The behavior of these functions is</font><br /><font color="green">// undefined in the presence of code which has been compiled</font><br /><font color="green">// without frame pointers.</font><br /><br />FOUNDATION_EXPORT unsigned NSCountFrames(void);<br /><font color="green">// Returns the number of call frames on the stack. The behavior</font><br /><font color="green">// of this functions is undefined in the presence of code which</font><br /><font color="green">// has been compiled without frame pointers.</font><br /><br /><font color="green">/**************** Autorelease pool debugging ****************/<br /></font><br /><font color="green">// Functions used as interesting breakpoints in a debugger</font><br />FOUNDATION_EXPORT void _NSAutoreleaseNoPool(void *object);<br /><font color="green">// Called to log the "Object X of class Y autoreleased with no</font><br /><font color="green">// pool in place - just leaking" message.</font><br /><br />FOUNDATION_EXPORT void _NSAutoreleaseFreedObject(void *freedObject);<br /><font color="green">// Called when a previously freed object would be released</font><br /><font color="green">// by an autorelease pool. See +enableFreedObjectCheck: below.</font><br /><br />FOUNDATION_EXPORT void _NSAutoreleaseHighWaterLog(unsigned int count);<br /><font color="green">// Called whenever a high water mark is reached by a pool.</font><br /><font color="green">// See +setPoolCountHighWaterMark: below.</font><br /><br />@interface <a name="NSAutoreleasePool">NSAutoreleasePool</a> (NSAutoreleasePoolDebugging)<br /><br />+ (void)enableRelease:(BOOL)enable;<br /><font color="green">// Enables or disables autorelease pools; that is, whether or</font><br /><font color="green">// not the autorelease pools send the -release message to their</font><br /><font color="green">// objects when each pool is released. This message affects only</font><br /><font color="green">// the pools of the autorelease pool stack of the current thread</font><br /><font color="green">// (and any future pools in that thread). The "default default"</font><br /><font color="green">// value can be set in the initial environment when a program</font><br /><font color="green">// is launched with the NSEnableAutoreleasePool environment</font><br /><font color="green">// variable (see notes at the top of this file) -- as thread</font><br /><font color="green">// pool-stacks are created, they take their initial enabled</font><br /><font color="green">// state from that environment variable.</font><br /><br />+ (void)showPools;<br /><font color="green">// Displays to stderr the state of the current thread's</font><br /><font color="green">// autorelease pool stack.</font><br /><br />+ (void)resetTotalAutoreleasedObjects;<br />+ (unsigned)totalAutoreleasedObjects;<br /><font color="green">// Returns the number of objects autoreleased (in ALL threads,</font><br /><font color="green">// currently) since the counter was last reset to zero with</font><br /><font color="green">// +resetTotalAutoreleasedObjects.</font><br /><br />+ (void)enableFreedObjectCheck:(BOOL)enable;<br /><font color="green">// Enables or disables freed-object checking for the pool stack</font><br /><font color="green">// of the current thread (and any future pools in that thread).</font><br /><font color="green">// When enabled, an autorelease pool will call the function</font><br /><font color="green">// _NSAutoreleaseFreedObject() when it is about to attempt to</font><br /><font color="green">// release an object that the runtime has marked as freed (and</font><br /><font color="green">// then it doesn't attempt to send -release to the freed storage).</font><br /><font color="green">// The pointer to the freed storage is passed to that function.</font><br /><font color="green">// The "default default" value can be set in the initial</font><br /><font color="green">// environment when a program is launched with the</font><br /><font color="green">// NSAutoreleaseFreedObjectCheckEnabled environment variable</font><br /><font color="green">// (see notes at the top of this file) -- as thread pool-stacks</font><br /><font color="green">// are created, they take their initial freed-object-check state</font><br /><font color="green">// from that environment variable.</font><br /><br />+ (unsigned int)autoreleasedObjectCount;<br /><font color="green">// Returns the total number of autoreleased objects in all pools</font><br /><font color="green">// in the current thread's pool stack.</font><br /><br />+ (unsigned int)topAutoreleasePoolCount;<br /><font color="green">// Returns the number of autoreleased objects in top pool of</font><br /><font color="green">// the current thread's pool stack.</font><br /><br />+ (unsigned int)poolCountHighWaterMark;<br />+ (void)setPoolCountHighWaterMark:(unsigned int)count;<br /><font color="green">// Sets the pool count high water mark for the pool stack of</font><br /><font color="green">// the current thread (and any future pools in that thread). When</font><br /><font color="green">// 'count' objects have accumulated in the top autorelease pool,</font><br /><font color="green">// the pool will call _NSAutoreleaseHighWaterLog(), which</font><br /><font color="green">// generates a message to stderr. The number of objects in the</font><br /><font color="green">// top pool is passed as the parameter to that function. The</font><br /><font color="green">// default high water mark is 0, which disables pool count</font><br /><font color="green">// monitoring. The "default default" value can be set in the</font><br /><font color="green">// initial environment when a program is launched with the</font><br /><font color="green">// NSAutoreleaseHighWaterMark environment variable (see notes at</font><br /><font color="green">// the top of this file) -- as thread pool-stacks are created,</font><br /><font color="green">// they take their initial high water mark value from that</font><br /><font color="green">// environment variable. See also +setPoolCountHighWaterResolution:.</font><br /><br />+ (unsigned int)poolCountHighWaterResolution;<br />+ (void)setPoolCountHighWaterResolution:(unsigned int)res;<br /><font color="green">// Sets the pool count high water resolution for the pool stack of</font><br /><font color="green">// the current thread (and any future pools in that thread). A</font><br /><font color="green">// call to _NSAutoreleaseHighWaterLog() is generated every multiple</font><br /><font color="green">// of 'res' objects above the high water mark. If 'res' is zero</font><br /><font color="green">// (the default), only one call to _NSAutoreleaseHighWaterLog() is</font><br /><font color="green">// made, when the high water mark is reached. The "default default"</font><br /><font color="green">// value can be set in the initial environment when a program is</font><br /><font color="green">// launched with the NSAutoreleaseHighWaterResolution environment</font><br /><font color="green">// variable (see notes at the top of this file) -- as thread</font><br /><font color="green">// pool-stacks are created, they take their initial high water</font><br /><font color="green">// resolution value from that environment variable. See also</font><br /><font color="green">// +setPoolCountHighWaterMark:.</font><br /><br />@end<br /><br /><font color="green">/**************** Allocation statistics ****************/<br /></font><br /><font color="green">// The statistics-keeping facilities generate output on various types of</font><br /><font color="green">// events. Currently, output logs can be generated for use of the zone</font><br /><font color="green">// allocation functions (NSZoneMalloc(), etc.), and allocation and</font><br /><font color="green">// deallocation of objects (and other types of lifetime-related events).</font><br /><br /><font color="green">// This boolean is obsolete and unused</font><br />FOUNDATION_EXPORT BOOL NSKeepAllocationStatistics;<br /><br /><font color="green">// Object allocation event types</font><br />#define NSObjectAutoreleasedEvent 3<br />#define NSObjectExtraRefIncrementedEvent 4<br />#define NSObjectExtraRefDecrementedEvent 5<br />#define NSObjectInternalRefIncrementedEvent 6<br />#define NSObjectInternalRefDecrementedEvent 7<br /><br /><br />FOUNDATION_EXPORT void NSRecordAllocationEvent(int eventType, ...);<br /><font color="green">// Notes an object or zone allocation event and various other</font><br /><font color="green">// statistics, such as the time and current thread. The additional</font><br /><font color="green">// arguments to be passed to this function vary by the type of</font><br /><font color="green">// event. The behavior is undefined (and likely catastrophic) if</font><br /><font color="green">// the correct arguments for 'eventType' are not provided.</font><br /><font color="green">//</font><br /><font color="green">// The parameter prototypes for each event type are shown below.</font><br /><font color="green">// NSRecordAllocationEvent(NSObjectAutoreleasedEvent, curObj)</font><br /><font color="green">// NSRecordAllocationEvent(NSObjectExtraRefIncrementedEvent, curObj)</font><br /><font color="green">// NSRecordAllocationEvent(NSObjectExtraRefDecrementedEvent, curObj)</font><br /><font color="green">// NSRecordAllocationEvent(NSObjectInternalRefIncrementedEvent, curObj)</font><br /><font color="green">// NSRecordAllocationEvent(NSObjectInternalRefDecrementedEvent, curObj)</font><br /><font color="green">//</font><br /><font color="green">// Only the Foundation should have reason to use many of these.</font><br /><font color="green">// Do not call NSRecordAllocationEvent(NSZoneMallocEvent, ...)</font><br /><font color="green">// after NSZoneMalloc(), for example, in your own code because</font><br /><font color="green">// NSZoneMalloc() has already done this for you. The only common</font><br /><font color="green">// use of this function should be with these two events:</font><br /><font color="green">// NSObjectInternalRefIncrementedEvent</font><br /><font color="green">// NSObjectInternalRefDecrementedEvent</font><br /><font color="green">// when a class overrides -retain and -release to do its own</font><br /><font color="green">// reference counting.</font><br /><font color="green">//</font><br /><br /></code><br />＋＋＋＋＋<br /><img src ="http://www.cppblog.com/walkklookk/aggbug/156007.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/walkklookk/" target="_blank">佳为好友</a> 2011-09-17 10:11 <a href="http://www.cppblog.com/walkklookk/archive/2011/09/17/156007.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转：GDB和ObjC结合的高级技巧</title><link>http://www.cppblog.com/walkklookk/archive/2011/09/17/156006.html</link><dc:creator>佳为好友</dc:creator><author>佳为好友</author><pubDate>Sat, 17 Sep 2011 02:10:00 GMT</pubDate><guid>http://www.cppblog.com/walkklookk/archive/2011/09/17/156006.html</guid><wfw:comment>http://www.cppblog.com/walkklookk/comments/156006.html</wfw:comment><comments>http://www.cppblog.com/walkklookk/archive/2011/09/17/156006.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/walkklookk/comments/commentRss/156006.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/walkklookk/services/trackbacks/156006.html</trackback:ping><description><![CDATA[转：<a title="http://support.apple.com/kb/TA45906?viewlocale=en_US" href="http://support.apple.com/kb/TA45906?viewlocale=en_US">http://support.apple.com/kb/TA45906?viewlocale=en_US</a><br /><br />Advanced Debugging Techniques<br /><br />Backtraces<br /><br />Gdb provides a set of commands that allow you to examine the state of your application. Use the backtrace command (bt) to find out where control has come from, based on a list of stack frames. Use the frame command (f) to choose which of those stack frames is selected. The info frame, info locals, and info args commands provide you with more information about the chosen frame. Remember that gdb's command line interpreter can evaluate any C or Objective-C expression, so when your application is stopped in gdb, you can examine and set variables of your program, make function calls, send messages to objects, and so on.<br /><br />Backtrace output looks like this:<br /><br />(gdb) bt<br />#0 -[MovieMgr fetchMovies] (self=0x439750, _cmd=0x402127) at MovieMgr.m:28<br />#1 0x401030 in -[MovieMgr init] (self=0x439750, _cmd=0x310255d3)<br />at MovieMgr.m:12<br />#2 0x320434c0 in +[NSObject new] ()<br />#3 0x31017842 in objc_msgSendv ()<br />#4 0x320410d5 in -[NSInvocation invoke] ()<br />#5 0x540b4134 in NMSPerformSelector ()<br />#6 0x540bf01e in -[WOObjCExpression evaluateInScope:debugger:] ()<br />#7 0x540bb575 in -[WOBinaryExpression evaluateInScope:debugger:] ()<br />#8 0x540bc8d5 in -[WOExpressionStatement executeInScope:debugger:] ()<br />#9 0x540c27b0 in -[WOStatements executeInScope:debugger:] ()<br />#10 0x540bc6a7 in -[WOCompoundStatement executeInScope:debugger:] ()<br />#11 0x540bd45f in -[WOMethod executeInParentScope:debugger:forSelf:arguments:]<br />()<br />#12 0x540be5a5 in -[WOModule evaluateMethodNamed:forSelf:count:arguments:inScope<br />:debugger:] ()<br />#13 0x540b7289 in _NMSGenericMethod ()<br />#14 0x540b72dd in -[_NMSScriptedClassShadow _genericVararg:] ()<br />#15 0x4201d5ad in -[WOComponent(WOComponentPrivate) _initWithName:] ()<br />#16 0x4201e7bb in -[WOComponentDefinition(WOComponentGeneration) componentInstan<br />ce] ()<br />#17 0x42018a5f in -[WOApplication(WOPageManagement) pageWithName:] ()<br />#18 0x4201932f in -[WOApplication(WORequestHandlingInternals) _handleRequestInPr<br />eparedSession] ()<br />#19 0x42019277 in -[WOApplication(WORequestHandlingInternals) _handleRequestInPr<br />eparedApplication] ()<br />#20 0x42019915 in -[WOApplication(WORequestHandling) handleRequest:] ()<br />#21 0x4202a0c5 in -[WODefaultAdaptor handleConnection:] ()<br />#22 0x3203946f in _postNotification ()<br />#23 0x32039d6a in -[NSNotificationCenter postNotificationName:object:userInfo:]<br />()<br />#24 0x320604ad in -[NSConcreteFileHandle handleMachMessage:] ()<br />#25 0x3206f0c6 in -[NSRunLoop acceptInputForMode:beforeDate:] ()<br />#26 0x3206f268 in -[NSRunLoop runMode:beforeDate:] ()<br />#27 0x42018d75 in -[WOApplication(WORunning) run] ()<br />#28 0x4012d6 in main (argc=4, argv=0x436430) at main.m:183<br />#29 0x40144c in mainCRTStartup ()<br />(gdb)<br /><br />You can then inspect the frames.<br /><br />(gdb) f 12<br />#12 0x540be5a5 in -[WOModule evaluateMethodNamed:forSelf:count:arguments:inScope<br />:debugger:] ()<br />(gdb)<br /><br />If you have the symbols, you can use info args to print the function's arguments and info locals to print the local variables:<br /><br />(gdb) info args<br />self = (MovieMgr *) 0x439750<br />_cmd = (struct objc_selector *) 0x402127<br />(gdb) info locals<br />self = (MovieMgr *) 0x439750<br />fetchSpec = (EOFetchSpecification *) 0x448a80<br />(gdb)<br /><br />If you do not have the symbols, you can still get to some of the argument information by using the frame pointer and offsets. (These offsets vary based on system architecture.)<br /><br />p *(id *)($fp + 8) - prints the receiver of the message (often the same as self)<br />p *(SEL *)($fp + 12) - prints the selector (the method that was called)<br />p *(id *)($fp + 16) - prints argument 1<br />p *(id *)($fp + 20) - prints argument 2<br />p *(id *)($fp + 24) - prints argument 3<br /><br />(gdb) f 12<br />#12 0x540be5a5 in -[WOModule evaluateMethodNamed:forSelf:count:arguments:inScope<br />:debugger:] ()<br />(gdb) p *(id *)($fp + 8)<br />$4 = (WOModule *) 0x43ab70<br />(gdb) p *(id *)($fp + 16)<br />$5 = (NSInlineCString *) 0x428ff0<br />(gdb) po $5<br />init<br />(gdb) p *(id *)($fp + 20)<br />$6 = (WOScriptedClass(/WebObjects/Projects/batch.woa/Main.wo/Main) *) 0x432ea0<br />(gdb)<br /><br />For convenience, you may want to create user-defined commands for these offsets in your .gdbinit file.<br /><br />＋＋＋＋＋<br /><img src ="http://www.cppblog.com/walkklookk/aggbug/156006.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/walkklookk/" target="_blank">佳为好友</a> 2011-09-17 10:10 <a href="http://www.cppblog.com/walkklookk/archive/2011/09/17/156006.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转:将Debug信息写入到文件中 --Write Debug Output to a File</title><link>http://www.cppblog.com/walkklookk/archive/2011/09/17/156003.html</link><dc:creator>佳为好友</dc:creator><author>佳为好友</author><pubDate>Sat, 17 Sep 2011 02:05:00 GMT</pubDate><guid>http://www.cppblog.com/walkklookk/archive/2011/09/17/156003.html</guid><wfw:comment>http://www.cppblog.com/walkklookk/comments/156003.html</wfw:comment><comments>http://www.cppblog.com/walkklookk/archive/2011/09/17/156003.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/walkklookk/comments/commentRss/156003.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/walkklookk/services/trackbacks/156003.html</trackback:ping><description><![CDATA[转:<a title="http://iphonedevelopertips.com/general/write-debug-output-to-a-file.html" href="http://iphonedevelopertips.com/general/write-debug-output-to-a-file.html">http://iphonedevelopertips.com/general/write-debug-output-to-a-file.html</a><br />
<p>NSLog definitely has its place in debugging. In a previous post I shared a version I wrote that skips displaying the date and object information, you can read more about the debug command I use on a regular basis <a title="http://iphonedevelopertips.com/debugging/yet-another-debug-output-nslog-replacement.html" href="http://iphonedevelopertips.com/debugging/yet-another-debug-output-nslog-replacement.html">here</a>.<br /><span id="more-1386"></span></p>
<p>At some point, capturing debug statements to a file (versus the console) can be helpful to track down bugs. The good news is that you can continue to use NSLog (and/or the debug command from the previous post) by simply making a change to where stderr is directed. </p>
<p>For example, to re-direct stderr to a file &#8220;debug.txt&#8221; off the root of the system drive, follow these steps:</p>
<div class="wp_syntax">
<div class="code"><pre style="font-family: monospace" class="objc"><span style="font-style: italic; color: rgb(17,116,10)">// Create OS specific path</span><br /><span style="color: rgb(166,19,144)">const</span> <span style="color: rgb(166,19,144)">char</span> <span style="color: rgb(0,34,0)">*</span>path <span style="color: rgb(0,34,0)">=</span> <span style="color: rgb(0,34,0)">[</span><span style="color: rgb(191,29,26)">@</span><span style="color: rgb(191,29,26)">"/debug.txt"</span> fileSystemRepresentation<span style="color: rgb(0,34,0)">]</span>;<br />
&nbsp;<br /><span style="font-style: italic; color: rgb(17,116,10)">// Specify stderr writes to a file (truncating contents first) </span><br /><span style="color: rgb(166,19,144)">freopen</span><span style="color: rgb(0,34,0)">(</span>path, <span style="color: rgb(191,29,26)">"w"</span>, <span style="color: rgb(166,19,144)">stderr</span><span style="color: rgb(0,34,0)">)</span>;</pre></div></div>
<p>Each time you run your application, the contents of the file &#8220;debug.txt&#8221; will be truncated and all output written to the file. If you would like to keep a running tally of debug output across invocations of the application, you can change &#8216;freopen&#8217; to append contents as follows:</p>
<div class="wp_syntax">
<div class="code"><pre style="font-family: monospace" class="objc"><span style="font-style: italic; color: rgb(17,116,10)">// Specify stderr appends to a file</span><br /><span style="color: rgb(166,19,144)">freopen</span><span style="color: rgb(0,34,0)">(</span>path, <span style="color: rgb(191,29,26)">"a"</span>, <span style="color: rgb(166,19,144)">stderr</span><span style="color: rgb(0,34,0)">)</span>;</pre></div></div><br />+++++<br /><img src ="http://www.cppblog.com/walkklookk/aggbug/156003.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/walkklookk/" target="_blank">佳为好友</a> 2011-09-17 10:05 <a href="http://www.cppblog.com/walkklookk/archive/2011/09/17/156003.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转: xcode不能调试解决方案</title><link>http://www.cppblog.com/walkklookk/archive/2011/09/17/155996.html</link><dc:creator>佳为好友</dc:creator><author>佳为好友</author><pubDate>Sat, 17 Sep 2011 01:54:00 GMT</pubDate><guid>http://www.cppblog.com/walkklookk/archive/2011/09/17/155996.html</guid><wfw:comment>http://www.cppblog.com/walkklookk/comments/155996.html</wfw:comment><comments>http://www.cppblog.com/walkklookk/archive/2011/09/17/155996.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/walkklookk/comments/commentRss/155996.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/walkklookk/services/trackbacks/155996.html</trackback:ping><description><![CDATA[转:<a title="http://blog.csdn.net/hyugahinat/archive/2009/09/10/4538877.aspx" href="http://blog.csdn.net/hyugahinat/archive/2009/09/10/4538877.aspx">http://blog.csdn.net/hyugahinat/archive/2009/09/10/4538877.aspx</a><br />
<p>Ｑ：建一个基于视图的工程 然后build and debug 但是程序会自动退出调试状态 &nbsp;在debugger console下查看出以上信息 这是什么原因呀 新建的工程我可一点都没动呀我是在pc上装的mac</p>
<p>Ａ：XCode--Preferences...--Debugging--Symbol Lazy Options把下面那个选项(load symbol lazily)去掉,再设个断点就可以调试了</p><br /><br />++++++<br /><img src ="http://www.cppblog.com/walkklookk/aggbug/155996.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/walkklookk/" target="_blank">佳为好友</a> 2011-09-17 09:54 <a href="http://www.cppblog.com/walkklookk/archive/2011/09/17/155996.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>