2017-07-06 72 views
0

在Xcode 8.3.3,C++ 11中內置的調試版本之間的行爲出現意外差異Cocos2d-x框架。我使用emplace()方法來填充std :: map(_randomLetterChancesToAppear),它正確地在調試中構建,但似乎不會在發佈中填充。這種說法在同一時間被絆倒當兩個值預期等於:調試和發佈版本之間std :: map行爲的差異(Xcode 8.3,C++ 11,Cocos2d-x)

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

當一個發佈版本的斷言人次,_randomLetterChancesToAppear似乎並沒有包含任何數據。 (爲了測試這個,在相關的情況下,我創建了一個重複的Xcode方案到我的默認移動方案,並且將Run build配置更改爲發佈以允許我測試具有附加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"); 
    } 
} 

爲什麼這種方法可能在兩個構建配置之間表現不同有什麼想法?

+0

他可能是未定義的行爲又名。 UB。你應該嘗試使用像valgrind這樣的工具,Xcode可能有類似的東西。這可以告訴你,例如:如果你正在使用未初始化的內存或寫入未分配的內存。有許多其他工具可用於尋找此類錯誤。 – Jonas

+1

'char letterChanceKey [1]; sprintf(letterChanceKey,「%c」,alphabetChar);'這會通過緩衝區溢出展現未定義的行爲。 'letterChanceKey'沒有空間用於終止NUL。 –

+0

非常感謝伊戈爾!增加緩衝區大小似乎解決了問題。 –

回答

0

積分爲Igor Tandetnik爲答案。

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

沒有留下足夠的空間用於終止NUL並導致緩衝區溢出。增加緩衝區大小解決了問題。

謝謝伊戈爾!