標籤:android blog ar os java for on 資料 2014
cocos2dx在android下是採用Paint來產生圖片然後在CCLabelTTF裡顯示的,它具體的代碼都在java類Cocos2dxBitmap裡,產生完成之後會調用一個jni函數將結果傳給cpp層,cpp層靠一個static變數來與java層交換資料,具體如下
BitmapDC &dc = sharedBitmapDC(); CC_BREAK_IF(! dc.getBitmapFromJava(pText, nWidth, nHeight, eAlignMask, pFontName, nSize)); // assign the dc.m_pData to m_pData in order to save time m_pData = dc.m_pData; CC_BREAK_IF(! m_pData);
這裡有個問題,sharedBitmapDC是一直共用的,它的dc.m_pData永遠儲存的是上一次的資料,如果某種原因java層調用的時候失敗了,那麼cpp層繼續的話,就會拿到上上次的資料,但是這個資料是由cpp層負責free的,於是就會出現double free導致程式崩潰。我們在實際中就碰到了這個情況,當時崩潰的棧告訴我們的是CCImage析構裡出現問題
CCImage::~CCImage(){ CC_SAFE_DELETE_ARRAY(m_pData);#if (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) || (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) CC_SAFE_DELETE(m_ft);#endif}
可是單純看CCImage的代碼是看不問題的,而且如果這裡有問題,那麻煩大了。最終檢查了之後還是確認cpp部分可能會隱藏bug,於是將上面CCImage裡修改如下
BitmapDC &dc = sharedBitmapDC(); CC_BREAK_IF(! dc.getBitmapFromJava(pText, nWidth, nHeight, eAlignMask, pFontName, nSize)); // assign the dc.m_pData to m_pData in order to save time m_pData = dc.m_pData; dc.m_pData = NULL; CC_BREAK_IF(! m_pData);
這樣一來,cpp層肯定不會再出現double free了,於是再測,這個時候發現java層拋異常了,之前的異常由於程式退出根本就沒列印得出來。再去追查java層,發現具體原因是
setContentSize之後,java層根據ContentSize判斷出來,字型根本放不進去,於是它認為建立出來的Bitmap的高度是0,而Bitmap根本不允許建立高度為0的,於是異常了。我解決的辦法是至少讓它顯示出來一行一列,這樣我們看到顯示就知道哪裡出問題了,而不是直接崩潰。
從這個問題再一次印證了,fail early, fail loud的編程習慣,否則一個簡單問題就變成複雜問題了。
cocos2dx 2.x版本在android下CCLabelTTF的一個bug