2016-04-24 127 views
0

我正在製作一個程序利用類,並得到一個奇怪的錯誤,但只有偶爾。我相信這個錯誤是由堆棧溢出引起的,或者是我的一個指針搞亂了。當我運行我的程序時,它會循環幾次並將我的記錄類添加到列表中,但是一旦它到達第三個項目,我將收到SIGSEGV Segmentation Fault錯誤。當我使用GDB並遍歷我的程序並嘗試打印'current - > id'的值時,它說「不能訪問地址爲0xe0的內存」。這是我遇到的代碼中的一部分,應該執行深入複製到另一個列表中。堆棧溢出或指針錯誤?

list&list :: operator=(const list& list1) 
{ 
    rec * current = NULL; 
    current = list1.first; 

    rec temprec; 
    char tempid[15]; 
    char tempfirst[15]; 
    char templast[15]; 
    int answersin[10]; 

    while(current -> id != NULL) 
    { 
     //Printing Data to follow program easier 
     cout << endl; 
     cout << tempid; 
     cout << endl; 
     cout << current -> id; //Receive error on this line 
     cout << endl; 

     strcpy(tempid, current -> id); 
     strcpy(tempfirst, current -> firstname); 
     strcpy(templast, current -> lastname); 
     for(int i=0; i<10; i++) 
     { 
      answersin[i]=current -> a[i]; 
     } 
     temprec.SetData(tempid, tempfirst, templast, answersin); 
     if (AddItem(temprec)) 
     { 
      cout << "Success."; 
     } 
     else 
     { 
      cout << "Failed."; 
     } 
     current = current -> next;   
    } 

} // End Operator = 

如果它是堆棧溢出什麼是最好的方法去解決它?我不確定應該將堆存儲在堆中。我檢查了我的指針,他們對我來說似乎沒問題,但我可能是錯的。任何幫助是極大的讚賞!

編輯1:我發現我的問題是我傳入的列表不是空終止的。如果我在主程序中列出一個列表,我沒有任何問題,但是當我在這個函數中創建列表時,它會混淆(仍然只是有時候,我只相信更大的列表)。該功能應該將選定人員的答案與另一人的答案進行比較,並製作一份包含最匹配記錄的列表。

list list :: BestMatch (char *IDinput) 
{ 
    rec * ptr;  // pointer for traversing 
    ptr = first;  // set pointer to the beginning of the list 
    rec * CompPtr; // pointer for traversing to compare answers 
    CompPtr = first; // set compare pointer to the beginning of the list 
    int compare = 0; // variable to compare strings 
    int score = 0; 
    int currentMax = 0; 
    list returnList; 

    while (ptr) // loops through until the end of the list 
    { 
     compare = strcmp(IDinput, ptr -> id); // compare id to be Matched to the id that ptr points to 
     if (compare == 0) // "if id to be Matched matches an id in the list" 
     { 
      break; // break from loop 
     } 
     ptr = ptr -> next; // go to the next node in the list to be checked 
    } 
    if (!ptr) // If ptr = NULL, meaning the end of the list was reached 
    { 
     cout << "ID for Match Not found." << endl; 
     return returnList; 
    } 
    while (CompPtr) // loops through until all the answers are compared 
    { 
     score = ComputeScore (ptr, CompPtr); // Compares answers from id to be Matched to current node in the list 
     if (score == 0) 
     { 
      ; // Do nothing 
     } 
     else if (score > currentMax) 
     { 
      returnList.DeleteList();   // Delete all other items in list because new score is greater than all of them 
      if (returnList.AddItem(*CompPtr)) // Add new item with highest score to the list 
      { 
       cout << "\nSuccess!\n"; 
      } 
      else 
      { 
       cout << "\nMatch.\n"; 
      } 
      currentMax = score;    // Make the new current max be equal to the score of the new greatest match 
     } 
     else if (score == currentMax) 
     { 
      returnList.AddItem(*CompPtr); // Simply add to list due to same score 
     } 
     else //(score < currentMax) 
     { 
      ; //Do nothing. 
     } 
     CompPtr = CompPtr -> next; // advance to the next node to be compared 
    } 
    ptr = NULL; 
    CompPtr = NULL; 
    returnList.PrintList(0); 
    return returnList; 
} // End BestMatch 

所使用的ComputeScore功能:

int list :: ComputeScore (rec* Input, rec* Compare) 
{ 
    int ReturnScore =0; 
    int compare =0; 

    // Prevents comparing to self 
    compare = strcmp(Input -> id, Compare -> id); 
    if (compare == 0) // id match found 
    { 
     return 0; // cannot match with self 
    } 

    // Check to see if gender is appropriate for match 
    if (Input -> a[9] != Compare -> a[0]) 
    { 
     return 0; 
    } 
    else 
    { 
     ; 
    } 

    // Check to see if school year is appropriate for class 
    if (Input -> a[7] == 1 && Compare -> a[1] != 1) 
    { 
     return 0; 
    } 
    else if (Input -> a[7] == 2 && Compare -> a[1] != 2) 
    { 
     return 0; 
    } 
    else if (Input -> a[7] == 3 && Compare -> a[1] != 3) 
    { 
     return 0; 
    } 
    else if (Input -> a[8] == 4 && Compare -> a[2] != 4) 
    { 
     return 0; 
    } 
    else 
    { 
     ; // Do nothing & Continue 
    } 

    // Compare other answers 
    if (Input -> a[2] == Compare -> a[2]) 
    { 
     ReturnScore = ReturnScore + 1; 
    } 

    if (Input -> a[3] == Compare -> a[3]) 
    { 
     ReturnScore = ReturnScore + 1; 
    } 

    if (Input -> a[4] == Compare -> a[4]) 
    { 
     ReturnScore = ReturnScore + 1; 
    } 

    if (Input -> a[5] == Compare -> a[5]) 
    { 
     ReturnScore = ReturnScore + 1; 
    } 

    if (Input -> a[6] == Compare -> a[6]) 
    { 
     ReturnScore = ReturnScore + 1; 
    } 

    if (Input -> a[8] == Compare -> a[8]) 
    { 
     ReturnScore = ReturnScore + 1; 
    } 

    return ReturnScore; 

} // End ComputeScore 

,並可能從我的頭文件有幫助的一些附加信息:

class rec 
{ 
public: 
    rec (char * i, char * fn, char * ln, int * ans); //constructor 
    rec (void);          //default constructor 
    rec& operator=(const rec& r);      
    rec (const rec& r);        //copy constructor 
    ~rec(); 
    void SetData(char * id_in, char * fn, char * ln, int * ans_in);  
    char ReturnID (const rec& r); 
    void Print();  
    friend class list; 
private: 
    char id[15]; 
    char firstname[15]; 
    char lastname[15]; 
    int a[10]; 
    rec* prev; 
    rec* next; 
}; 

class list 
{ 
public: 
    list (void);       //default constructor 
    list& operator=(const list& list1); //deep copy one list to another 
    int AddItem (const rec& r); 
    int DeleteItem (char* delid); 
    void PrintList (int order); 
    int Count(char *FileName); 
    void DeleteList (); 
    int ReadData (char* file1, char* file2); 
    int WriteData (char* wfile1, char* wfile2); 
    int ComputeScore (rec* Input, rec* Compare); 
    list BestMatch (char* IDinput); 
    list TopTen (char* IDinput); 
private: 
    rec * first; 
    rec * last; 
}; 
+0

「在地址0xe0的無法訪問存儲」聽起來確實像你通過一個NULL指針試圖取消引用一個成員變量(如結構*的東西= NULL; something- > foo = 123,其中foo位於結構內存區域頂部的偏移量0x0e處) –

+0

我以爲相同,但發現由於某種原因,我的列表不會終止。最後一個項目的下一個字段包含地址0xe0,這是給我的問題。 – Lareaper

+0

您可以在代碼中使用信號處理程序捕獲SIGSEGV,並追蹤問題的根源。 http://stackoverflow.com/questions/2663456/how-to-write-a-signal-handler-to-catch-sigsegv –

回答

2

最後一個元素列表,其next將爲NULL,因此在current = current -> next;之後,當前將爲NULL,並且您尚未通過取消引用它。因此,我建議在while循環中增加此項檢查:

while(current && (current -> id != NULL)) { 
    ... 
} 
+0

我試過這個,仍然得到錯誤。我爲傳入的列表添加了一個額外的打印函數(我也打印了列表中每個項目的前一個和下一個的內存地址),並且我意識到我的列表由於某種原因未終止,並且相反,最後一項的下一個字段的地址爲0xe0。我之前從來沒有遇到過這個問題,因爲我一直在修改和添加一段時間,所以我不確定發生了什麼。 – Lareaper

+0

@Lareaper所以你發現有一個無效的地址0xe0,好的,請發佈構建列表的代碼。 – fluter

+0

我不確定這是問題所在,還是在我正在使用的其他類功能之一中,但我會發布一些更多的代碼! – Lareaper