调试和发布版本之间std :: map行为的差异(Xcode 8.3,C ++ 11,Cocos2d-x)

时间:2017-07-06 18:19:03

标签: xcode c++11 stl cocos2d-x release

在Cocos2d-x框架上运行Xcode 8.3.3,C ++ 11中构建的调试版本之间的行为意外差异。我使用emplace()方法填充std :: map(_randomLetterChancesToAppear),它正确地在调试中构建,但似乎没有在发布中填充。在两个值预期相等的时候,这个断言正在被触发:

CC_ASSERT(outCellDetail._randomLetterChancesToAppear.size() == alphabetCount);

当断言在发布版本中跳转时,_randomLetterChancesToAppear似乎不包含任何数据。 (为了测试它,如果相关,我为我的默认移动方案创建了一个重复的Xcode方案,并将Run build配置更改为release以允许我测试附加了IDE的发布版本。 )

以下是违规方法:

void GameDataController::PopulateIndividualCellChancesToAppear(CellDetail &outCellDetail, const rapidjson::Value &cellDetailObject, const GameDetail& constGameDetail) const
{
    cocostudio::DictionaryHelper* dicTool = cocostudio::DictionaryHelper::getInstance();
    CC_ASSERT(dicTool->checkObjectExist_json(cellDetailObject, "LetterChancesToAppear"));
    CCASSERT(constGameDetail._alphabet.length() > 0, "Zero-length alphabet!");

    const rapidjson::Value& letterChancesObject = dicTool->getSubDictionary_json(cellDetailObject, "LetterChancesToAppear");

    // iterate through each letter in this game detail's alphabet
    const int alphabetCount = static_cast<int>(constGameDetail._alphabet.length());
    std::vector<char> lettersNeedingChances;
    for (int i = 0; i < alphabetCount; ++i)
    {
        // if a given alphabet letter has a chance to appear, save it.
        const char alphabetChar = constGameDetail._alphabet.at(i);
        char letterChanceKey[1];
        sprintf(letterChanceKey, "%c", alphabetChar);
        if (dicTool->checkObjectExist_json(letterChancesObject, letterChanceKey))
        {
            const float ChanceToAppear = dicTool->getFloatValue_json(letterChancesObject, letterChanceKey);
            CC_ASSERT(!std::isnan(ChanceToAppear));
            CC_ASSERT(ChanceToAppear >= 0.0f);
            outCellDetail._randomLetterChancesToAppear.emplace(alphabetChar, !std::isnan(ChanceToAppear) ? ChanceToAppear : 0.0f);
        }
        else
        {
            // ... otherwise, store the letter in a list of letters without assigned chances.
            lettersNeedingChances.push_back(alphabetChar);
        }
    }

    // fill in missing chances to appear.
    if (lettersNeedingChances.size() > 0)
    {
        float defaultRemainingChance = 1.0f / static_cast<float>(alphabetCount);
        CC_ASSERT(!std::isnan(defaultRemainingChance));
        CC_ASSERT(defaultRemainingChance > FLT_EPSILON);
        for (const char remainingChar : lettersNeedingChances)
        {
            CCLOG("Character %c doesn't have a chance to appear specified. Using default %f", remainingChar, defaultRemainingChance);
            outCellDetail._randomLetterChancesToAppear.emplace(remainingChar, defaultRemainingChance);
        }
    }
    // vvvv THIS ASSERT IS FAILING IN RELEASE, BUT NOT IN DEBUG BUILD CONFIGURATIONS. vvvvv
    CC_ASSERT(outCellDetail._randomLetterChancesToAppear.size() == alphabetCount);

    // normalize chances to appear.
    float chanceTotal = 0.0f;
    for(auto iterator = outCellDetail._randomLetterChancesToAppear.begin();
        iterator != outCellDetail._randomLetterChancesToAppear.end();
        iterator++)
    {
        chanceTotal += iterator->second;
    }

    if (std::abs(chanceTotal - 1.0f) > FLT_EPSILON)
    {
        float adjustmentFactor = 1.0f / chanceTotal;
        float adjustedChanceTotal = 0.0f;
        for(auto iterator = outCellDetail._randomLetterChancesToAppear.begin();
            iterator != outCellDetail._randomLetterChancesToAppear.end();
            iterator++)
        {
            iterator->second = iterator->second * adjustmentFactor;
            adjustedChanceTotal += iterator->second;
        }
        CCASSERT(std::abs(adjustedChanceTotal - 1.0f) <= FLT_EPSILON, "adjustedChanceTotal != 1.0f");
    }
}

有关为什么此方法在两种构建配置之间可能表现不同的任何想法?

1 个答案:

答案 0 :(得分:0)

获得答案的归功于Igor Tandetnik

    char letterChanceKey[1];
    sprintf(letterChanceKey, "%c", alphabetChar);

没有为终止NUL留下足够的空间并导致缓冲区溢出。增加缓冲区大小可以解决问题。

谢谢你,伊戈尔!