Xcode EXC_BAD_ACCESS 错误调试
在 Objective-C 编程中遇到 EXC_BAD_ACCESS 问题的时候,通过简单常规的手段很难发现问题。
EXC_BAD_ACCESS 这个错误,可以这么说,90%的错误来源在于对一个已经释放的对象进行release操作。
Objective-C 这段代码有三个致命问题,1,内存泄露。2,错误释放。3,造成 EXC_BAD_ACCESS 错误。
1、为工程运行时加入 NSZombieEnabled 环境变量,并设为启用,则在 EXC_BAD_ACCESS 发生时,XCode 的 Console 会打印出问题描述。
双击 XCode 工程中,Executables 下的 可执行模组
在弹出窗口中,Arguments Tab页的 [Variables to be set in the environment],添加 NSZombieEnabled,并设定为 YES,点击选中复选框启用此变量。
这样,运行上述 Objective-C 时会看到控制台输出:
house591(4584) malloc: process 4404 no longer exists, stack logs deleted from /tmp/stack-logs.4404.house591.pxtCfB.index
这条消息对于定位问题有很好的提示作用。但是很多时候,只有这条提示是不够的,我们需要更多的提示来帮助定位问题,这时候再加入 MallocStackLogging 来启用malloc记录。
当错误发生后,在终端执行:
malloc_history ${App_PID} ${Object_instance_addr} 则会获得相应的 malloc 历史记录,比如对于上一个控制台输出
在控制台输出错误信息:
malloc_history ${App_PID} ${Object_instance_addr}
例如:malloc_history 4871 0×6624820
后面的pid和16进制的内存地址是xcode的console 里面得到的。
看最后一行:
ALLOC 0×6624820-0x662482f [size=16]: thread_a0bd4540 |start | main | UIApplicationMain | GSEventRun | GSEventRunModal | CFRunLoopRunInMode | CFRunLoopRunSpecific | __CFRunLoopRun | __CFRunLoopDoSource1 | __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ | PurpleEventCallback | _UIApplicationHandleEvent | -[UIApplication sendEvent:] | -[UIWindow _sendTouchesForEvent:] | -[UIControl touchesEnded:withEvent:] | -[UIControl(Internal) _sendActionsForEvents:withEvent:] | -[UIControl sendAction:to:forEvent:] | -[UIApplication sendAction:to:from:forEvent:] | -[UIBarButtonItem(UIInternal) _sendAction:withEvent:] | -[UIApplication sendAction:to:from:forEvent:] | -[HouseSearchController btnConditionPressed:] | -[UIViewController presentModalViewController:withTransition:] | -[UIViewController _tryRecursivelyPresentModalViewController:withTransition:] | -[UIViewController presentModalViewController:withTransition:] | -[UIWindowController transition:fromViewController:toViewController:target:didEndSelector:] | -[UIWindow _setRotatableClient:toOrientation:updateStatusBar:duration:force:] | -[UIViewController window:willAnimateRotationToInterfaceOrientation:duration:] | -[CALayer layoutIfNeeded] | CALayerLayoutIfNeeded | -[CALayer layoutSublayers] | -[UILayoutContainerView layoutSubviews] | -[UINavigationController _startDeferredTransitionIfNeeded] | -[UINavigationController _startTransition:fromViewController:toViewController:] | -[UINavigationController _layoutViewController:] | -[UINavigationController _computeAndApplyScrollContentInsetDeltaForViewController:] | -[UIViewController contentScrollView] | -[UIViewController view] | -[SetSearchConditionViewController viewDidLoad] | -[__NSPlaceholderArray initWithContentsOfFile:] | +[NSArray(NSArray) newWithContentsOf:immutable:] | _NSParseObjectFromASCIIPropertyListOrSerialization | CFPropertyListCreateFromXMLData | CFPropertyListCreateWithData | _CFPropertyListCreateWithData | __CFTryParseBinaryPlist | __CFBinaryPlistCreateObject2 | __CFBinaryPlistCreateObject2 | CFStringCreateWithCharactersNoCopy | __CFStringCreateImmutableFunnel3 | _CFRuntimeCreateInstance | malloc_zone_malloc
就可以找到问题所在了。
Objective-C 这段代码有三个致命问题,1,内存泄露。2,错误释放。3,造成 EXC_BAD_ACCESS 错误。
1, NSString* s = [[NSString alloc]initWithString:@”This is a test string”]; 创建了一个 NSString Object,随后的 s = [s substringFromIndex:[s rangeOfString:@"a"].location]; 执行后,导致创建的对象引用消失,直接造成内存泄露。
2,错误释放。[s release]; 这个问题,原因之一是一个逻辑错误,以为 s 还是我们最初创建的那个 NSString 对象。第二是因为从 substringFromIndex:(NSUInteger i) 这个方法返回的 NSString 对象,并不需要我们来释放,它其实是一个被 substringFromIndex 方法标记为 autorelease 的对象。如果我们强行的释放了它,那么会造成 EXC_BAD_ACCESS 问题。
3: EXC_BAD_ACCESS。由于 s 指向的 NSString 对象被标记为 autorelease, 则在 NSAutoreleasePool 中已有记录。但是由于我们在前面错误的释放了该对象,则当 [pool drain] 的时候,NSAutoreleasePool 又一次的对它记录的 s 对象调用了 release 方法,但这个时候 s 已经被释放不复存在,则直接导致了 EXC_BAD_ACCESS问题。
分布式版本控制Mercurial搭建文檔
在官網下載最新的mac安裝包。按照提示信息安裝。 安裝完成後可使用
tar zxvf mercurial-1.8.1.tar.gz
cd mercurial-1.8.1
make
make install
hg debuginstall
BALSAMIQ MOCKUPS 停止發放測試用序列號
慚愧啊~前幾天裝的用BALSAMIQ MOCKUPS,昨天到期,以前試用的序列號也提示過期,於是按照網上說的在blog寫一片推廣文,然後發郵件給natalie@balsamiq.com,就會得到一個體驗用的序列號。
今天收到balsamiq發的郵件,失望至極啊。。。臉都發燒了,畢竟還是第一次跟老外用英文交流,蹩腳的英文讓我自己都冒汗。話說mockups的米太貴了,不是我能承受的起。。或者說傳統觀念的影響(我太無恥了),花600多塊買個不怎麼常用的軟件。。。有些奢侈啊,還不知道以後更新怎麼辦。apple就是搶的,買個ilife08,如果升級還得買。
拿朋友的話說:“想當年如果有自己的筆記本電腦就很牛逼了”,我想說:“如果我能買的起正版軟件就相當牛逼了。”
廢話不多說,附上balsamiq的原文
we no longer offer free evaluation licenses to
bloggersbecause we changed our trial to be a fully-featured 7-day
demo.
用BALSAMIQ MOCKUPS 做iphone原型图
公司同事介绍用BALSAMIQ MOCKUPS画产品原型图,之前在windows上安装可以使用,可换成mac后却不能使用了。
Balsamiq Mockups出自加利福尼亚州的Balsamiq工作室,创始人Peldi在2008年6月推出了这款手绘风格的产品原型设计工具,并广受好评。2年多来,Balsamiq工作作为一个微型独立软件开发商,专注于Mockups的开发设计,仅3周便实现了盈利,18个月内销售额达到200万美元,用户端数量超过10万个,这与Balsamiq Mockups的市场用户细分的成功以及产品特性是分不开的。
下面是我用 Balsamiq Mockups 做的一个原型,比较简单。
下载和安装Balsamiq Mockups
官方下载
点击图标直接安装即可,安装内容包括Adobe AIR环境以及Mockups主体桌面程序:

当你无法安装Balsamiq Mockups或者没时间安装时,Balsamiq还为你提供了在线Web版本的Mockups。
emacs mac 下快捷鍵
網上都說emacs是最強大的編輯器,但是入門真的很困難。要自己配置,還要熟悉掌握那一陀一陀的快捷鍵。配置是基於lisp語言,網上有大把的教程,也可以在emacs下按 ctr + h i 然後按 m鍵, 輸入 Elisp 就可以看到完整的lisp的文檔。也可以到查看中文。
打開,關閉,保存
ctr + x ctr + f (打開一個文件)
ctr + x ctr + s (保存)
ctr + x k (關閉,需要確認)
移動光標
alt + a (移動到行首,不包含縮進空格)
alt + e (移動到行尾,不包含縮進、空格)
ctr + a (移動到行首)
ctr + e (移動到行尾)
alt + { (移動到前段落)
alt + } (移動到下個段落)
ctr + f (向後移動(一個字符))
ctr + b (向前移動(一個字符))
alt + f (向後移動(一個單詞))
alt + b (向前移動(一個單詞))
復制、粘貼、刪除
alt + d (向後刪除一個單詞)
alt + del(向前刪除一個單詞,注:del是mac的鍵,win下請用previous)
ctr + k (刪除一行)
alt + w (復制,注: alt只有win下才有,mac 下用M(commond)鍵表示,想半天才想起來)
ctr + y (粘貼)
窗口切換
ctr + x 1 把當前視窗設位最大(填充)
ctr + x 2 切成兩個一樣的窗口
ctr + x o 在多個窗口中切換
mac 快捷键备忘
终于有了俺的第一台mac,先谢谢老总!
以前觉得apple的产品都是苹果迷们捧出来的,使用时才发现自己的肤浅。
至于原因网上大把,就自己而言,光多点触摸板就足够让我掉大牙了。一个手指,两个手指,三个手指,四个手指已经把大部分的操作从鼠标转到触摸板,再配合mac、opt、shift、ctr等键基本上就可以脱离鼠标。终于明白老外为什么对苹果那么痴迷了。
这两天总结了mac的几个快捷键,记录下来用以炫耀吧!嘿嘿!
cmd + moshi(空格) = 切换输入法,如果按住cmd键不放,可以用上下键来选择系统提供的输入法。而不是每次都要 cmd + moshi。
由于习惯了win下的home跟end,mac上找不到这两个键,可使用:
shift + cmd + 左右方向键来替代。
shift + cmd + 4(3) 切屏。
cmd + w (关闭当前视窗)
cmd + q (退出当前应用程式)
shift + ctr + enj = 关闭屏幕
shift + opt + enj = 打开屏幕
shift + cmd + enj = 系统休眠
cmd + c = 复制
cmd +
v = 粘贴
或使用 ctr + 鼠标单击 选择复制粘贴。
cmd + tab 应用程式间切换
cmd + ~ 窗口间切换
也可用4个手指在触摸板向上(下)滑动来切换,或者4个手指左右滑动来选择。
在有scroll条的窗口,可以用2个手指上下滑动来拉动显示。
等等等等,功能太强大了。最牛X的是,开箱后基本上所用的东西都已经有安装好了,都不需要在找这样那样的应用来扩充。之前还想从windows向linux迁移,有了mac后就感觉到ubuntu X windows是多么的慢。如果可以,hp也要考虑装mac了,不知到能不能装成功。
有意栽花花不開,無心插柳柳成蔭。
在線人數大約在3000左右,用兩臺機器跑,在高峰時會出現連不了memcache的情況,以前只是11211端口佔用比較多,但昨天出現不能連memcache。老問題了,一直因為非常重要或者很重要的事情而放到出現問題才會解決(11211端口的問題在很久以前就提出)。
連接memcached的地方有兩處,session和DB Cache,我先試著改session:
- function open() {
- global $_memcache;
- $_memcache = memcache_pconnect(HOST,PORT);
- }
- // session close
- function close() {
- global $_memcache;
- memcache_close($_memcache);
- }
- // session gc
- function gc($key) {
- global $_memcache;
- memcache_close($_memcache);
- }
- // session destroy
- function destroy($key) {
- global $_memcache;
- memcache_close($_memcache);
- }
- // session read
- function read($key) {
- global $_memcache;
- $_memcache->get($key);
- }
- // session write
- function write($key,$val) {
- global $_memcache;
- memcache_set($_memcache,$key,$val,0,SESSION_MAX_LIFTTIME);
- }
- // 初始化
- function init()
- {
- ini_set(‘session.use_trans_sid’,0);
- ini_set(‘session.gc_maxlifetime’,SESSION_MAX_LIFTTIME);
- ini_set(‘session.use_cookies’, 1);
- ini_set(‘session.cookie_path’, ‘/’);
- ini_set(‘session.cookie_domain’,’.’.BASE_URL);
- session_module_name(‘user’);
- session_set_save_handler(
- ‘open’,
- ‘close’,
- ‘read’,
- ‘write’,
- ‘destroy’,
- ‘gc’
- );
- session_start();
- }
- init();
發現問題照舊,再改成:
- $_session_save_path = "tcp://192.XX.XX.XX:11211";
- ini_set(‘session.save_handler’, ‘memcache’);
- ini_set(‘session.save_path’, $_session_save_path);
- session_start();
還是一樣,眼看半天過去,問題都沒找到。看樣子問題不出在session,那就是db cache了,只有連接沒有斷開,不斷創建新的連接,才會有那麼多的端口被佔用,俺想到一個最簡單的辦法,設計模式的單例模式不就解決類似的問題嗎?
先看看單例模式的類圖:
- class Obj_Memcache {
- private static $_instance = null;
- private function __construct(){}
- private function __clone(){}
- public static function getInstance()
- {
- if (self::$_instance == null) {
- self::$_instance = new Memcache();
- self::$_instance->connect(CFG_DB_CACHE_HOST, CFG_DB_CACHE_PORT);
- }
- return self::$_instance;
- }
- }
找到實現cache的地方:
替換為:
- $this->Mem = Obj_Memcache::getInstance();
看看結果:
今天觀察看看,應該不是蓋的。。
雷死人的hosts和resolv.conf
今天算是碰到怪事了,做的儲值模塊,因為代碼去抓取遠程資料庫的數據,在Server端已寫好api,直接調用就可以了。所以就用fsockopen來建立連接,問題出來了,不管怎麼寫,死活抓不到資料。
- if (!$_fp) {
- throw new Exception($_error_msg.$_errorno."\n");
- }
一直提示
- Connection timed out 110
換成curl後還是不可以~在命令行下運行
- curl -G http://sub.domain.com/XX/xx/xx
出現couldn’t connect to host.
但是在內部的測試機卻是正常。就是說內部機訪問subdomain,dns可以正常解析,換服務器就不可以了。
在hosts中加入
- 192.X.X.X sub.domain.com
指定ip後再試,ok了。
整理的htc desire 大陆和香港间的差异
除了接口、htc 小工具、GPS,操作系统不一样,其他的都一样。
php5 iterator - 迭代器
上一篇我提到php的spl(php 标准库),今天刚好又用到iterators,觉得非常方便。于是从网上找了一些资料,结合我蹩脚的能力写了下来。
先看看iterators有哪些内容:
图中有数组、文件、目录、对象和相对应实现递归的迭代器。拿数组说事:
- $_demo_arr = array(‘name’ => ‘OGX’, ‘sex’ => ‘B’, ‘age’ => ’100′, ‘color’ => ‘yellow’, 300);
正常我们来遍历数组:
- foreach ($_demo_arr AS $_key => $_val) {
- echo $_key . ‘==’ . $_val;
- }
- // 或者
- while (list($_key,$_val) = @each($_demo_arr)) {
- echo sprintf("%s == %s",$_key,$_val);
- }
结果如下:
同样的数组,我改为迭代器遍历,代码如下:
- $_obj_iterator = new ArrayIterator($_demo_arr);
- while ($_obj_iterator->valid()) {
- echo "i’m iterator: \r\n";
- echo sprintf("%s == %s",$_obj_iterator->key(),$_obj_iterator->current()) . "\r\n";
- }
结果如下:
当然,你可以使用别的iterator来实现你需要的功能,例如遍历目录、遍历对象等等。具体就不介绍了,也没能力写得更好。如有遗漏或者错误之处还请见谅。











