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

调试版本和发布版本之间std::map行为的差异(Xcode 8.3,C+;+;11,Cocos2d-x),xcode,c++11,stl,cocos2d-x,release,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); 当assert在发布版本中跳闸

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

CC_ASSERT(outCellDetail._randomLetterChancesToAppear.size() == alphabetCount);
当assert在发布版本中跳闸时,randomLetterChancesToAppear似乎不包含任何数据。(为了测试这一点,如果相关的话,我创建了一个复制的Xcode方案到我的默认移动方案,并将运行构建配置更改为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");
    }
}
void GameDataController::PopulateIndividualCellChancesToAppear(CellDetail&outCellDetail,const rapidjson::Value&cellDetailObject,const GameDetail&const GameDetail)const
{
cocostudio::DictionaryHelper*dicTool=cocostudio::DictionaryHelper::getInstance();
CC_ASSERT(dicTool->checkObjectExist_json(cellDetailObject,“lettchancestoappear”);
CCASSERT(constGameDetail._alphabet.length()>0,“零长度字母表!”);
const rapidjson::Value&letterChancesObject=dicTool->getSubDictionary_json(cellDetailObject,“LetterChancesToAppear”);
//在游戏细节的字母表中重复每个字母
const int alphabetCount=static_cast(constGameDetail._alphabet.length());
std::矢量字母增量;
对于(int i=0;icheckObjectExist_json(lettchanceobject,lettchancekey))
{
const float ChanceToAppear=dicTool->getFloatValue_json(lettchanceobject,lettchancekey);
CC_ASSERT(!std::isnan(ChanceToAppear));
CC_断言(偶然出现>=0.0f);
outCellDetail._randomLetterChancesToAppear.emplace(alphabetChar,!std::isnan(ChanceToAppear)?ChanceToAppear:0.0f);
}
其他的
{
//…否则,请将该字母存储在没有指定机会的字母列表中。
字母变长。推回(alphabetChar);
}
}
//填补错过的出现机会。
如果(lettersNeedingChances.size()>0)
{
float defaultRemainingChance=1.0f/静态施法(字母计数);
CC_ASSERT(!std::isnan(defaultRemainingChance));
CC_ASSERT(defaultRemainingChance>FLT_EPSILON);
for(常量字符剩余字符:字母更改)
{
CCLOG(“字符%c没有机会出现指定的字符。使用默认的%f”,remainingChar,defaultRemainingChance);
outCellDetail.\u随机字母机会出现在安放位置(保留字符,默认保留机会);
}
}
//此断言在版本中失败,但在调试生成配置中失败。vvv
CC_ASSERT(outCellDetail._randomLetterChancesToAppear.size()=alphabetCount);
//使出现的机会正常化。
浮动通道总数=0.0f;
对于(自动迭代器=outCellDetail._randomLetterChancesToAppear.begin();
迭代器!=outCellDetail.\u randomLetterChancesToAppear.end();
迭代器++)
{
chanceTotal+=迭代器->秒;
}
如果(标准::abs(信道总数-1.0f)>FLT_ε)
{
浮动调整系数=1.0f/通道总数;
浮动调整通道总=0.0f;
对于(自动迭代器=outCellDetail._randomLetterChancesToAppear.begin();
迭代器!=outCellDetail.\u randomLetterChancesToAppear.end();
迭代器++)
{
迭代器->第二个=迭代器->第二个*调整因子;
调整后的信道总数+=迭代器->秒;
}
CCASSERT(std::abs(adjusted chancetotal-1.0f)答案归谁

    char letterChanceKey[1];
    sprintf(letterChanceKey, "%c", alphabetChar);
没有为终止NUL留出足够的空间,导致缓冲区溢出。增加缓冲区大小修复了该问题


谢谢你,Igor!

他的行为可能是未定义的,即.UB。你应该尝试使用valgrind之类的工具,Xcode可能也有类似的功能。这可以告诉你:如果你正在使用未初始化的内存或写入未分配的内存。在寻找这类错误时,还有许多其他工具可供使用。
charletterChanceKey[1];sprintf(letterChanceKey,“%c”,alphabetChar);
这通过缓冲区溢出的方式表现出未定义的行为。
letterChanceKey
没有空间容纳终止NUL。非常感谢Igor!增加缓冲区大小似乎解决了问题。