对于我的生活,我无法弄清楚出了什么问题。我知道错误发生在下面标记为displayQueue的函数中,但所有语法和逻辑似乎都是正确的。
Visual Studio给出了错误:“ex11_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 :(得分:4)
错误就在这一行,但为了学习,我不会给出正确的版本,只是提示一些:
newNode->link = back->link;
在执行此代码时,back
指向哪个节点?它的link
指向什么?您需要修改哪个节点link
?
至于自己找到这个,你可以使用调试器找出导致崩溃的行;这表明link
值存在问题。
P.S。您的复制构造函数实际上并不复制链接列表;它只是创建一个指向同一链表的新Queue对象,因此如果您向副本添加一个元素,它将显示在原始队列中。
答案 1 :(得分:2)
地址0xCDCDCDCD
的访问冲突意味着您的程序从未初始化的存储中加载了一个指针,然后取消引用它。 Microsoft的调试分配器将此模式用于新分配的未初始化存储,并在合适的编译模式下,也用于堆栈位置。如果将此未初始化的存储视为指针变量,则该指针中的模式可识别。而且,它几乎肯定是一个无效的指针,会触发异常。所以好处是快速捕获无效指针的使用,并且该模式告诉您原因很可能是未初始化的存储(尽管这不是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。基于&#34;内存中毒&#34;模式的调试不准确!)< / p>