0

C++ を初めて使用し、ベクトルを返す際に問題が発生しました。ブレークポイントを設定すると、配列は正しくなります (クエリから期待されるすべてのオブジェクトが取り込まれています)。しかし、それが返されると、エラーが発生します: EXC_BAD_ACCESS on line m_pComponentContainer->removeAll(); CCNode.cpp から

Cocos2dx フレームワークを広く使用していますが、このクラスには含まれていませんが、これは基本クラス (どの種類の CC オブジェクトからも継承されません) であるため、これは奇妙です。

これは、何かが割り当て解除されているためだと確信しています。ただし、私が言ったように、私は C++ に非常に慣れていないため、問題がどこにあるのかよくわかりません。メモリ管理について心配する前に、もう少し開発を進めたいと思っていました。

 int numberOfCards = DatabaseHelper::getNumberOfCards();

//cant be zero
assert(numberOfCards);

std::vector<CardSlot> returnArray(numberOfCards);

sqlite3_stmt * statement;

if (sqlite3_open(this->dbpath.c_str(),&this->cardWarsDB) == SQLITE_OK)
{
    const char* query_stmt = "select ID, HP, MP, AbilityText from Cards WHERE ID IN (SELECT DISTINCT cardsID FROM Deck WHERE name = 'All')";

    if (sqlite3_prepare_v2(this->cardWarsDB, query_stmt, -1, &statement, NULL) == SQLITE_OK)
    {
        while (sqlite3_step(statement) == SQLITE_ROW)
        {
            CardSlot *aCard;

            const char* cardID = (const char*)sqlite3_column_text(statement, 0);
            const char* cardHP = (const char*)sqlite3_column_text(statement, 1);
            const char* cardMP = (const char*)sqlite3_column_text(statement, 2);
            const char* cardAbility = (const char*)sqlite3_column_text(statement, 3);

            if (cardID != NULL) {
                std::string imageName = ".png";
                imageName = cardID + imageName;
                aCard = (CardSlot *)CardSlot::spriteWithFile(imageName.c_str());
            }

            if (cardID != NULL) {
                aCard->cardID = std::string(cardID);
                cocos2d::CCLog("DB returned results, cardID: %s",aCard->cardID.c_str());
            }
            if (cardHP != NULL) {
                aCard->cardHP = std::string(cardHP);
                cocos2d::CCLog("DB returned results, cardHP: %s",aCard->cardHP.c_str());
            }
            if (cardMP != NULL) {
                aCard->cardMP = std::string(cardMP);
                cocos2d::CCLog("DB returned results, cardMP: %s",aCard->cardMP.c_str());
            }
            if (cardAbility != NULL) {
                aCard->cardAbility = std::string(cardAbility);
                cocos2d::CCLog("DB returned results, cardAbility: %s",aCard->cardAbility.c_str());
            }

            numberOfCards--;

            returnArray[numberOfCards] = *aCard;

        }
        sqlite3_finalize(statement);
    }
    sqlite3_close(this->cardWarsDB);
    return returnArray;
}

スタック トレースのスクリーンショットを次に示します。私はそれを見ていましたが、CardSlot オブジェクトが原因のようです。しかし、それらを「保持」する方法はまだわかりませんが、Cocos のドキュメントを見てみましょう。

ここに画像の説明を入力

注1

4

3 に答える 3

0

コードを編集して、配列をオブジェクトで渡したり埋めたりするのではなく、より多くのポインターを使用するようにしました。しかし、それを修正するのに大いに役立ったのは、cocos2d::CCArray代わりに aを使用したことだと思います。std::vector. 私のクラスのほとんどは Cocos2d クラス (CCSprites と CCLayers) の子であるため、独自の配列データ型を使用することは理にかなっています。

cocos2d::CCArray DatabaseHelper::getAllCards()
{
    int numberOfCards = DatabaseHelper::getNumberOfCards();

    //cant be zero
    assert(numberOfCards);

    cocos2d::CCArray returnArray(numberOfCards);

    sqlite3_stmt * statement;

    if (sqlite3_open(this->dbpath.c_str(),&this->cardWarsDB) == SQLITE_OK)
    {
        const char* query_stmt = "select ID, HP, MP, AbilityText from Cards WHERE ID IN (SELECT DISTINCT cardsID FROM Deck WHERE name = 'All')";

        if (sqlite3_prepare_v2(this->cardWarsDB, query_stmt, -1, &statement, NULL) == SQLITE_OK)
        {
            while (sqlite3_step(statement) == SQLITE_ROW)
            {
                CardSlot* aCard;

                const char* cardID = (const char*)sqlite3_column_text(statement, 0);
                const char* cardHP = (const char*)sqlite3_column_text(statement, 1);
                const char* cardMP = (const char*)sqlite3_column_text(statement, 2);
                const char* cardAbility = (const char*)sqlite3_column_text(statement, 3);

                if (cardID != NULL) {
                    std::string imageName = ".png";
                    imageName = cardID + imageName;
                    aCard = CardSlot::spriteWithFile(imageName.c_str());
                }

                if (cardID != NULL) {
                    aCard->cardID = std::string(cardID);
                    cocos2d::CCLog("DB returned results, cardID: %s",aCard->cardID.c_str());
                }
                if (cardHP != NULL) {
                    aCard->cardHP = std::string(cardHP);
                    cocos2d::CCLog("DB returned results, cardHP: %s",aCard->cardHP.c_str());
                }
                if (cardMP != NULL) {
                    aCard->cardMP = std::string(cardMP);
                    cocos2d::CCLog("DB returned results, cardMP: %s",aCard->cardMP.c_str());
                }
                if (cardAbility != NULL) {
                    aCard->cardAbility = std::string(cardAbility);
                    cocos2d::CCLog("DB returned results, cardAbility: %s",aCard->cardAbility.c_str());
                }

                numberOfCards--;

                returnArray.addObject(aCard);

            }
            sqlite3_finalize(statement);
        }
        sqlite3_close(this->cardWarsDB);
        return returnArray;
    }

    //incase sql fails, close db and created a "FAILED" card
    sqlite3_close(this->cardWarsDB);
    cocos2d::CCLog("DB returned error: cant open char catagories file");
    cocos2d::CCArray failedReturnArray(1);
    CardSlot * aCard;
    aCard->cardID = std::string("FAILED");
    aCard->cardHP = std::string("FAILED");
    aCard->cardMP = std::string("FAILED");
    aCard->cardAbility = std::string("FAILED");
    failedReturnArray.addObject(aCard);
    return failedReturnArray;
}

また、誰かがここで気にする場合は、CardSlot です (それほど重要ではなく、現時点ではコンストラクターのみをビルドしました)。

CardSlot * CardSlot::spriteWithFile(const char *pszFileName)
{

    CCLOG("CardSlot::spriteWithFile");
    CardSlot * aCard = new CardSlot();
    if (aCard && aCard->initWithFile(pszFileName))
    {
        aCard->cardID = pszFileName;
        aCard->scheduleUpdate();
        aCard->autorelease();
        return aCard;
    }
    CC_SAFE_DELETE(aCard);
    return NULL;
}

私が心配しているのは、CCArray がポインターであるべきだと思うことだけです。しかし、現在は機能しており、すべてのメモリ管理の「取引のトリック」を学習するのに間に合うでしょう.C++で作業すればするほど.

すべての助けをしてくれた@nneonneoに感謝します。あなたの修正がうまくいったと確信しています。私はできる限りあなたを1upしましたが、実際にはこれが私が実装した「答え」です。

于 2013-08-07T16:59:27.873 に答える
-1

returnArray関数に対してローカルに宣言され、関数が戻るときに割り当てが解除されます。staticとして宣言するか、宣言を関数の外に移動する必要があります。

于 2013-08-05T07:49:25.550 に答える