2014-04-19 67 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。基于“内存中毒”模式的调试并不准确!)

相关问题