2014-09-11 125 views
-1

第一次使用的用戶,它似乎從其他職位是個案的基礎。那麼,我是一名自學成才的C++語言程序員。於是,我終於學會了動態分配的內存,並開始思考使用CLI編程計算器的新方法,以輸入單個字符串並抽出答案。這個項目似乎是一個很好的起點,我開始研究解決方案。以下是我的結果:如何調試我的「堆損壞」? (C++)

#include <iostream> 
#include <string> 
using namespace std; 

int main() 
{ 
    string strInput; 
    cin >> strInput; 
    int nOperatorCount = 0; 
    for(int i = 0; i<(strInput.size());i++) 
    { 
     if(strInput[i]=='+'||strInput[i]=='-'||strInput[i]=='*'||strInput[i]=='/') 
      nOperatorCount++; 
    } 
    int *pnOperatorLocation = new int[nOperatorCount+1]; 
    int *pnOperatorType = new int[nOperatorCount]; 
    float *pnExpressions = new float[nOperatorCount + 1]; 
    pnOperatorLocation[0] = -1; 
    for(int i=0,j=0; i<(strInput.size());i++) 
    { 
     if(strInput[i]=='+') 
    { 
      pnOperatorLocation[j+1] = i; 
      pnOperatorType[j] = 0; 
      pnExpressions[j] = atoi((strInput.substr(pnOperatorLocation[j]+1,i)).c_str()); 
      j++; 
     } 
     if(strInput[i]=='-') 
     { 
      pnOperatorLocation[j+1] = i; 
      pnOperatorType[j] = 1; 
      pnExpressions[j] = atoi((strInput.substr(pnOperatorLocation[j]+1,i)).c_str()); 
      j++; 
     } 
     if(strInput[i]=='*') 
     { 
      pnOperatorLocation[j+1] = i; 
      pnOperatorType[j] = 2; 
      pnExpressions[j] = atoi((strInput.substr(pnOperatorLocation[j]+1,i)).c_str()); 
      j++; 
     } 
     if(strInput[i]=='/') 
     { 
      pnOperatorLocation[j+1] = i; 
      pnOperatorType[j] = 3; 
      pnExpressions[j] = atoi((strInput.substr(pnOperatorLocation[j]+1,i)).c_str()); 
      j++; 
     } 
     if(i==(strInput.size()-1)) 
      pnExpressions[j] = atoi((strInput.substr(pnOperatorLocation[j]+1,i+1)).c_str()); 
    } 
    for(int i=0;i<nOperatorCount+1;i++) 
    { 
     cout << "pnExpressions[" << i << "]: " << pnExpressions[i] << endl; 
    } 
    int nOperationsCount = 0; 
    for(int i=0;i<nOperatorCount;i++) 
    { 
     if(pnOperatorType[i]==2||pnOperatorType[i]==3) 
     { 
      if(pnOperatorType[i+1]==0||pnOperatorType[i+1]==1) 
       nOperationsCount++; 
      else if((i+1)==nOperatorCount) 
       nOperationsCount++; 
     } 
    } 
    cout << "nOperationsCount: " << nOperationsCount << endl; 
    float *pnNewExpressions = new float[nOperationsCount]; 
    for(int i=0,j=0;i<nOperatorCount;i++) 
    { 
     if(pnOperatorType[i]==2) 
     { 
      pnNewExpressions[j] = pnExpressions[i] * pnExpressions[i+1]; 
      if(pnOperatorType[i+1]==2||pnOperatorType[i+1]==3) 
      { 
       for(int k=i;k<nOperatorCount-i;k++) 
       { 
        if(pnOperatorType[k+1]==2) 
         pnNewExpressions[j] = pnNewExpressions[j] * pnExpressions[k+2]; 
        else if(pnOperatorType[k+1]==3) 
         pnNewExpressions[j] = pnNewExpressions[j]/pnExpressions[k+2]; 
        else 
         break; 
        if(k+1>=nOperatorCount) 
         break; 
       } 
      } 
      j++; 
     } 
     if(pnOperatorType[i]==3) 
     { 
      pnNewExpressions[j] = pnExpressions[i]/pnExpressions[i+1]; 
      if(pnOperatorType[i+1]==2||pnOperatorType[i+1]==3) 
      { 
       for(int k=i;k<nOperatorCount-i;k++) 
       { 
        if(pnOperatorType[k+1]==2) 
         pnNewExpressions[j] = pnNewExpressions[j] * pnExpressions[k+2]; 
        else if(pnOperatorType[k+1]==3) 
         pnNewExpressions[j] = pnNewExpressions[j]/pnExpressions[k+2]; 
        else 
         break; 
        if(k+1>=nOperatorCount) 
         break; 
       } 
      } 
      j++; 
     } 
     if(i+1>=nOperatorCount) 
      break; 
    } 
    for(int i=0;i<nOperationsCount;i++) 
    { 
     cout << "pnNewExpressions[" << i << "]: " << pnNewExpressions[i] << endl; 
    } 
    float fEvaluation; 
    if(pnOperatorType[0]==2||pnOperatorType[0]==3) 
     fEvaluation = pnNewExpressions[0]; 
    else 
     fEvaluation = pnExpressions[0]; 
    cout << "fEvaluation: " << fEvaluation << endl; 
    for(int i=0,j=1;i<nOperatorCount;i++) 
    { 
     if(pnOperatorType[i]==0) 
     { 
      if(pnOperatorType[i+1]==2||pnOperatorType[i+1]==3) 
      { 
       fEvaluation = fEvaluation + pnNewExpressions[j]; 
       j++; 
       cout << "fEvaluation: " << fEvaluation << endl; 
      } 
      else 
      { 
       fEvaluation = fEvaluation + pnExpressions[i+1]; 
       cout << "fEvaluation: " << fEvaluation << endl; 
      } 
     } 
     if(pnOperatorType[i]==1) 
     { 
      if(pnOperatorType[i+1]==2||pnOperatorType[i+1]==3) 
      { 
       fEvaluation = fEvaluation - pnNewExpressions[j]; 
       j++; 
       cout << "fEvaluation: " << fEvaluation << endl; 
      } 
      else 
      { 
       fEvaluation = fEvaluation - pnExpressions[i+1]; 
       cout << "fEvaluation: " << fEvaluation << endl; 
      } 
     } 
    } 
    cout << "fEvaluation: " << fEvaluation << endl; 
    delete[] pnOperatorLocation; 
    delete[] pnNewExpressions; 
    delete[] pnOperatorType; 
    delete[] pnExpressions; 
    system("pause"); 
    return 0; 
} 

我,如果你通過所有的閱讀非常非常非常非常抱歉,但我一直工作在一個已經歸結第二個副本少了很多複雜的,但我d爲什麼這個人突然停止工作。它用於大約10-15次使用,並且我使用了諸如「2 * 3 * 4 + 2 * 3 + 2」的輸入,並且它返回了「檢測到的腐敗筆:在正常的程序段#184之後」。所以我的問題是沒有任何人有任何想法如何我可以基於該錯誤消息進行調試?如果沒有,任何人都可以找到爲什麼我的代碼適用於像1 + 1和8 * 8這樣的簡單方程式,但不是像我期望的那樣複雜的方程式?

+0

有些事情要嘗試:'valgrind','efence',使用'at()'而不是'[]'來建立索引。 – 2014-09-11 02:06:54

+0

使用'std :: vector'刪除所有對'new []'和'delete []'的調用。一旦你這樣做了,使用vector的'at()'方法。一旦你排除了,然後用'[]'替換'at()'。 – PaulMcKenzie 2014-09-11 02:19:36

+0

只看代碼,'j'的使用看起來很可疑(你永遠不會真的檢查它的最大值,並且至少有一個循環從值'1'開始),因爲它可能會超過索引數組的邊界。 – lurker 2014-09-11 02:19:54

回答

0

的問題是,這部分代碼:

for (int i = 0, j = 0; i < nOperatorCount; i++) 
{ 
    if (pnOperatorType[i] == 2) 
    { 
     pnNewExpressions[j] = pnExpressions[i] * pnExpressions[i + 1]; // <<--- Error 

下標j是出在環路的2*3*4+2*3+2輸入界。

但這裏是我很快找到錯誤的原因 - 我用std::vector將所有這些調用替換爲new[]delete[]。由於您使用的是Visual Studio(錯誤是VS錯誤),因此DEBUG版本會自動檢查矢量數組邊界錯誤。出現的錯誤框會給你一個subscript out of range錯誤,因此VS IDE會直接發生違規行。

現在,std::vector::operator[]不檢查release版本中的邊界,通常operator []不應該這樣做。然而VS的調試庫打開了這個檢查。所以你可以說我正在利用Visual Studio提供的調試幫助。但是,只有當我改用std::vector時,我纔得到這個。

vector::at()函數的作用與使用[]的作用相同,但無論您是在運行發行版還是調試版,它都可以進行範圍檢查。我沒有在這裏用at()取代呼叫,但是如果由於某種原因[]沒有找到錯誤,我總是可以將代碼中的[]更改爲at(),直到出現錯誤爲止。

這裏的變化快速簡介:

#include <iostream> 
#include <string> 
#include <vector> 
//... 
std::vector<int> pnOperatorLocation(nOperatorCount + 1); 
std::vector<int> pnOperatorType(nOperatorCount); 
std::vector<float> pnExpressions(nOperatorCount + 1); 
//... 
std::vector<float> pnNewExpressions(nOperationsCount); 

此外,所有的呼叫delete[]的不再是必要的。

這是否解決了錯誤?不,我不想在解決方程式時檢查你的算法/邏輯。你仍然需要努力弄清楚這個循環的目的是什麼,以及爲什麼j超出界限。但它確實表明僅僅使用現代C++技術可能是有利的。使用new[]delete[]來創建動態數組是「舊式的」,而且實際上並不是必需的,除非您真的需要使用它。

基本上,你需要問自己 - 你想編寫一個方程求解器嗎?如果答案爲「是」,則使用可用的工具創建一個(如std::vector),然後繼續解決「簡單」錯誤,而不是使用指針進行對抗,並花費很多精力維護動態數組。

+0

Holy Moly。這是。哇。我認爲使用new []和delete []的指針數組是唯一的方法,但這個向量的東西似乎更容易動態分配內存!非常感謝你。由於我是新來的網站,有什麼辦法可以給你一個好評或什麼感謝,男人? PS:在重新組織我的程序並對其進行優化後,我能夠將j限制在範圍內,但是矢量事物使事情更易於閱讀和調試:) – 2014-09-11 08:30:15