2014-04-19 93 views
0

對於我的生活,我無法弄清楚發生了什麼問題。我知道錯誤發生在下面標記爲displayQueue的函數中,但是所有的語法和邏輯似乎都是正確的。令人沮喪的指針錯誤

Visual Studio給我錯誤:「exll_1.exe中的0x00215A86未處理的異常:0xC0000005:訪問衝突讀取位置0xCDCDCDE1。」不過說真的,我不知道這是指...

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

struct QueueNode { 
    string data; 
    QueueNode *link; 
}; 
typedef QueueNode* QueueNodePtr; 


class Queue { 
public: 
    // Constructors/Destructor. 
    Queue(); 
    Queue(const Queue& aQueue); 

    // Accessors. 
    bool empty() const; 
    void displayQueue(); 

    // Mutators. 
    void add(string item); 
    string remove(); // This should probably be replaced with pop and top - especially for displayQueue... empty() in functions can be replaced with count == 0. Yes, I will do this. 

private: 
    QueueNodePtr front;  // Points to head of linked-list queue. 
    QueueNodePtr back;  // Points to tail of linked-list queue. 
    size_t count; 
}; 

int main() { 
    Queue myQueue; 

    myQueue.add("abc"); 
    myQueue.add("def"); 
    myQueue.add("ghi"); 

    myQueue.displayQueue();  // The error is here somewhere. abc is printed and but nothing else. 

    system("pause"); 
    return 0; 
} 

Queue::Queue() { 
    front = NULL; 
    back = NULL; 
    count = 0; 
} 

Queue::Queue(const Queue& aQueue) { 
    front = aQueue.front; 
    back = aQueue.back; 
    count = aQueue.count; 
} 

bool Queue::empty() const { 
    if (count == 0) { 
     return 1; 
    } else { 
     return 0; 
    } 
} 

void Queue::displayQueue() { 
    // There is a problem here somewhere... 

    QueueNodePtr here = front; 
    for (int i = 0; i < count; i++) { 
     cout << here->data << endl; 
     here = here->link;  
    } 
} 

void Queue::add(string item) { 
    QueueNodePtr newNode; 
    newNode = new QueueNode; 

    if (count == 0) { 
     // If inserted in an empty queue, back and front point to same element. 
     newNode->data = item; 
     // newNode->link = NULL; // Not sure this part is even necessary. 
     back = newNode; 
     front = back; 
    } else { 
     // Otherwise, leave front pointer where it's at. 
     newNode->data = item; 
     newNode->link = back->link; 
     back = newNode; 
    } 
    count ++; 
} 

string Queue::remove() { 
    string returnString; 

    if (count == 0) { 
     return returnString; 
    } else if (count == 1) { 
     returnString = front->data; 
     front = NULL; 
     back = front; 
     count--; 
     return returnString; 
    } else { 
     returnString = front->data; 
     front = front->link; 
     count--; 
     return returnString; 
    } 
} 

編輯:如果誰能給我任何提示關於使用調試器來解決這樣的問題,或給我或許可以解釋這個鏈接這將不勝感激。

+0

您是否嘗試過調試器? – yizzlez

+0

是嗎?我相信這是我上面發佈的錯誤消息的來源。 – aaronmcavinue

回答

4

的錯誤是在這一行,但是對於學習的緣故,我不會給正確的版本,只是一些提示:

newNode->link = back->link; 

在其中正在執行該代碼的點,這節點確實back指向?它的link指向什麼?你需要修改哪個節點的link

至於自己找到這個,你可以使用調試器找出哪一行導致崩潰;這可能表明link值有問題。

P.S.你的拷貝構造函數實際上並不複製鏈表;它只是創建一個指向同一個鏈表的新Queue對象,所以如果你將一個元素添加到副本中,它將顯示在原始Queue中。

+0

如何使用調試器來做到這一點?現在我在調試器中,Visual Studio指向文件xstring中的一行。 – aaronmcavinue

+0

謝謝你的幫助,否則,但。我找出了什麼是錯的。 – aaronmcavinue

+0

@ featherlight53:使用Call Stack窗口查找您自己的源代碼中稱爲該代碼的行。 –

2

地址爲0xCDCDCDCD的訪問衝突意味着您的程序從未初始化的存儲中加載了一個指針,然後對其進行了解除引用。微軟的調試分配器使用這種模式用於新分配的未初始化的存儲,並且以合適的編譯模式,也用於堆棧位置。如果您將這樣的未初始化的存儲作爲指針變量處理,則該指針中的模式可識別。而且,它幾乎肯定是一個會觸發異常的無效指針。所以好處是無效指針的使用很快被捕獲,並且該模式告訴您原因很可能是未初始化的存儲(儘管這不是100%決定性的)。

例如:

struct contains_pointer { char *str; } *ptr = malloc(sizeof *ptr); 

strcpy(ptr->str, "abc"); // ptr->str is uninitialized 

或者:

int *pint; 
*pint = 0; // pint is uninitialized 

可以讓編譯器和庫覆蓋未初始化的存儲與像CDCDCD模式......可以說是相當有幫助的。您應該使用調試器精確定位崩潰的位置,然後從那裏開始工作:指針值的起源以及爲什麼不初始化。 (CDCDCDCD的錯誤指針可能導致其他方式:純粹的僥倖(不太可能)或免費使用後的錯誤:程序釋放一些內存,但繼續保留指向它的指針,而不使用它然後將內存重新分配給程序的其他部分,並將其標記爲未初始化的,並且偶然地,指針的原始用戶使用它,從內存中加載指針值,此時,一個CDCDCDCD指針的結果,所以它看起來像是一個use-before-init錯誤,實際上它是一個免費使用的bug。基於「內存中毒」模式的調試並不準確!)

相關問題