cocococococos 2 dx 2.xバージョンはandroidでCCLabelTTFの一つのbugです。

1764 ワード

cococococococococos 2 dxはandroidでPaintを採用して画像を生成し、CCLabelTTFに表示されています。具体的なコードはjava Cocococos 2 dxBitmapにあります。生成が完了したら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はずっと共有しています。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の部分にバグが隠されていることを確認し、上の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層を追跡して、具体的な原因を発見します。
set ContintSizeの後、java層はConttentSizeによって判断され、フォントが全然入らないので、作成されたBitmapの高さは0だと思っています。Bitmapは高さ0を作成することが全然許されません。私が解決した方法は少なくとも1行1列を表示させることです。このように私達は表示を見れば、どこが問題があるか分かります。直接的に崩壊するのではありません。
この問題からもう一回実証しました。fail early、fail loudのプログラミング習慣がないと、簡単な問題は複雑な問題になります。