2013-04-24 105 views
3

我碰到this錯誤來了,我看到itspopular周圍的變量C++堆棧被損壞

這個問題是相當混亂。我試圖找出哪個變量沒有被正確返回。將一個VC6項目移植到VS 2012時發現了此問題。這裏發生的是從數據庫中取出記錄集並將其轉入XML。

CGenAction GenAct(lUserId, O_ALARM, A_GET_TREE, ppALResult) 
{ 
    try 
    { 
     if (GenAct.BeginAction()) 
     { 
      checkuserPremission(info); 

      Result Res; 
      Dynaset DynaSet; 

      if (type.GetRecordSet(UserId, DynaSet, Res)) { 
       turnToXml(DynaSet,Res.m_bstrXMLString); 
      } 

      returnToUI(Res); 
     } 
    } 
} 

之前我就知道這種類型的bug我試圖做這樣的事情將ResDynaSet堆而不是堆棧內:

static Result * ResPtr = NULL; 

if(ResPtr != NULL) 
{ 
    delete ResPtr;   
} 

ResPtr = new Result(); 

這並沒有幫出來的問題。圍繞以下變量的堆棧已損壞:Res,DynaSet我會盡量縮小範圍,並且會盡快更新問題。

+2

我沒有看到任何可能導致此代碼中堆棧損壞的內容,您是否可以縮小範圍併發布該代碼? – 2013-04-24 08:49:43

+1

堆棧_which_變量?你的代碼中有很多,所以很難說沒有看到這些類的代碼。此外,這些「開始/結束宏」評論是什麼?這是一些宏的一部分嗎? '試圖找出哪個變量沒有被正確返回是相當混淆的 - 錯誤確切地說明哪個變量被損壞了,你能顯示完整的錯誤信息嗎? – 2013-04-24 09:35:58

回答

3

這是一個非常可靠診斷,VC6沒有它。虛假警告的可能性爲零。在移植之前,請注意,您的代碼庫中可能存在此問題。它警告的錯誤非常嚴重,通常在沒有幫助的情況下診斷非常困難。然而,它不一定是一個致命的問題,它可以長時間潛伏在代碼中。只是突然冒出來,並看到一個非常無辜的代碼更改肆虐。只需使用發佈版本設置來重建程序就足夠了,這使得診斷問題變得更加困難。

你的代碼片段太不透明,不能提出一個原因,未記錄的函數可能會導致它。我只會描述診斷工作的方式,以便您能夠調試它。

/RTC調試選項會導致編譯器在堆棧幀中分配局部變量,以便它們之間有空間。它會生成一個表格來標識這些空間。在函數入口處,這些空間填充值0xcc。在函數退出時,它會運行一個調試函數,該函數遍歷表並檢查這些空間是否仍包含0xcc。如果沒有,你會得到一個非常可靠的指示,表明代碼正在寫入它絕不應該觸及的堆棧幀位置。堆棧緩衝區溢出是一種可能性,還有其他的。

調試它的方法是使用Debug + Windows + Memory + Memory 1窗口。在函數的第一個語句中設置一個斷點。當它命中時,將EBP放入地址欄並打開頁面(注意堆棧增長下降)。您現在正在查看堆棧幀中的字節,切換到4字節視圖通常是最好的。嘗試將本地變量與您所看到的值相匹配。您還應該看到填充變量之間空格的0xcc值。現在使用調試器的StepOver命令開始步進。堆棧幀中更改的值以紅色着色。嘗試找到一個紅色的,幷包含0xcc之前。

你現在有一個字節的地址被重擊。重新啓動並使用數據斷點來讓調試器停止在重複該字節的語句處。