C++ Mysql null 引發的血案

代碼

出錯代碼段

bool CGameServer::getAccountInfoByUserId(int user_id, UserAccountData& data) {                                                                                          
    if (connectToLocalDB()) {
        log_error("connect to db failed");
        return false;
    }

    TLIB_DB_LINK *pTempDBLink = &m_stLDBLink;

    snprintf(pTempDBLink->sQuery[0], sizeof(pTempDBLink->sQuery[0]), 
        "select bind_mark, account, password, state, device_mark, country, tunnel, \
        register_version, transfer_code, bind_equipment from account_data where \
        user_id=%d", user_id);
    //......
                if (pTempDBLink->stRow[i]) {
                    data._transfer_code = pTempDBLink->stRow[i++];
                }

                if (pTempDBLink->stRow[i]) {
                    data._bind_equipment = atoi(pTempDBLink->stRow[i++]);
                }
   //......

問題代碼段

int CGameServer::setBindStatAndEquipment(int user_id, const std::string& equipment) {                                                                                   
    if (connectToLocalDB()) {
        log_error("connect to db failed");
        return -1;
    }    

    TLIB_DB_LINK *pTempDBLink = &m_stLDBLink;

    unsigned int equipment_size = 2 * equipment.size() + 2; 
    char* equipment_object = (char*)malloc(equipment_size);
    mysql_real_escape_string(&pTempDBLink->stMysqlConn.stMysql, (char*)equipment_object, 
        (char*)equipment.c_str(), equipment.size());

    snprintf(m_stLDBLink.sQuery[0], sizeof(m_stLDBLink.sQuery[0]), 
            "UPDATE account_data SET device_mark='%s', bind_equipment=1, \
            transfer_code=null WHERE user_id=%d", equipment_object, user_id);
            
    //......
}

錯誤分析

由於設置了 transfer_codenull,導致在獲取時,由於數據爲 null,導致 bind_equipment 也無法正常獲取到值。

細心的小夥子,想必你也看到了,SET 的時候 transf_code = null 和 bind_equipment 恰好是一組,所以後續獲取一定就出錯了。

爲什麼叫血案

  • 我自測未發現;
  • 測試也未發現;

最終這個問題被搞到線上環境了

爲什麼?

日本方需求如下:
用戶在 A 設備上獲取“遷移碼”,在 B 設備上使用該遷移碼,A 設備則不能再登錄遊戲,此後該賬號只能在 B 設備上使用。若想切換成其它設備,只需要在 B 設備上再獲取“遷移碼”在其它機器上使用即可

錯誤復現

  • 用戶在初始獲取遷移碼時,getAccountInfoByUserId 會被調用,此時會創建新的遷移碼;
  • 在另外的設備上使用遷移碼,setBindStatAndEquipment 會被調用;
  • 此時邏輯是正確的;
  • 但是在新的設備上獲取遷移碼時,getAccountInfoByUserId 會因爲 setBindStatAndEquipment 設置的數據,導致獲取的 bind_equipment0導致設備綁定的邏輯失效
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章