不過我也不打算寫太長,只寫要注意的地方就好了(因為太晚了~)。
我們先來看一段將Pixel array轉成UIImage的程式碼:
// 產生要畫的圖
unsigned char *pixels = malloc(nImageSize);
/*
* (省略繪圖步驟)
*/
// 用畫好的圖產生image用的context
CGContextRef context = CGBitmapContextCreate(pixels, width, height, ...);
// 用完的記得要還,要養成好習慣!
free(pixels);
// 產生UIImage
CGImageRef imageRef = CGBitmapContextCreateImage(context);
UIImage image = [UIImage imageWithCGImage:imageRef];
// 要release才不會leak
CGContextRelease(context);
CGImageRelease(imageRef);
這段code在simulator能將pixels正確地轉成UIImage,使用Intruments也沒有發現memory leak,看起來沒問題吧!
很不幸地,在iPhone上完全不是這麼回事,你只會看到一片空白。
你看出問題在哪了嗎?是的,問題就在於pixels太早free了!應該要產生完image之後再free pixels。在iPhone上執行時,一呼叫free就會將memory清掉了,但simulator是在Mac OS上面執行,呼叫free時模擬的行為可能跟在iOS上面不一樣(可能是因為Mac OS X有GC的機制而iOS沒有)。如果只在simulator上面執行,就永遠找不到這個bug了!
所以如果你有在程式碼中呼叫free的話,記得在實機上也要測過喔!
P.S. 以後有機會再來分享在Android emulator中開發的心得。話說用i7-2600K來跑Android emulator還是很慢啊...
2 Comment:
GC 應該是只有 Objective-C 的類別才有,std c lib "free" 應該沒做 GC。 只是不知道 OS X & iOS 的 memory allocation 演算法或 routine 有差別。有可能 OS X 的 free 之後,沒有馬上被清算,頂多 FMR 又資料沒有漏失,將錯就錯。iOS 因為是 embedded OS,有比較特別的 alloc/free 機制? 也許就清掉拿去重新利用了。
話說回來,既然有提供 memory space 給 CGBitmapContextCreate,那就變成要自己管理,所以馬上又 free 掉,再去做其他事情好像怪怪的。
jclin精闢的留言竟然被blogspot標成垃圾留言...遜~
補充說明一下,上面那段程式碼本來就是個bug,故意用註解來誤導的,就算當掉也只是剛好
但是Simulator有些東西就是沒辦法simulate
這種寫錯又不當,換環境才會發現的問題其實還不少
張貼留言