调试断言失败!奇怪的问题
Posted
技术标签:
【中文标题】调试断言失败!奇怪的问题【英文标题】:Debug Assertion Failed! Weird issue 【发布时间】:2015-11-27 02:28:40 【问题描述】:DebugAssertionFailed
AccessViolation
上面的两张图片显示了我遇到的错误。它们所处的顺序就是它们出现的顺序。 当第一个出现时,我点击重试,然后出现第二个,然后我点击继续,然后重复,当我最终中断时,出现一个标题为“msvcr120d.i386.pdb 未加载”的选项卡。当程序中断时,它会将我指向 DynamicQueue.h 代码的以下行:“delete temp;”
所有 dynamicqueue.h 和大部分 BinaryTree.h 都是直接从书中复制的,所以我不知道是什么导致了问题(主要是因为我不知道问题是什么)。 BinaryTree.h 中涉及转换为动态队列的部分是我写的。
以下是我的代码:
动态队列.h
#ifndef DYNAMICQUEUE_H
#define DYNAMICQUEUE_H
#include <iostream>
using namespace std;
//Dynamic Queue Template
template <class T>
class DynamicQueue
private:
struct QueueNode
T value;
QueueNode* next;
;
QueueNode* front;
QueueNode* rear;
int numItems;
public:
//Constructor
DynamicQueue();
//Destructor
~DynamicQueue();
//Queue Operations
void enqueue(T);
void dequeue(T &);
bool isEmpty() const;
bool isFull() const;
void clear();
;
//Constructor
template <class T>
DynamicQueue<T>::DynamicQueue()
front = nullptr;
rear = nullptr;
numItems = 0;
//Destructor
template <class T>
DynamicQueue<T>::~DynamicQueue()
clear();
//enqueue
template <class T>
void DynamicQueue<T>::enqueue(T item)
QueueNode* newNode = nullptr;
newNode = new QueueNode;
newNode->value = item;
newNode->next = nullptr;
if (isEmpty())
front = newNode;
rear = newNode;
else
rear->next = newNode;
rear = newNode;
numItems++;
//Dequeue
template <class T>
void DynamicQueue<T>::dequeue(T &item)
QueueNode* temp = nullptr;
if (isEmpty())
cout << "The queue is empty.\n";
else
item = front->value;
temp = front;
front = front->next;
delete temp; //When the program breaks, it points me here....
numItems--;
//isEmpty
template <class T>
bool DynamicQueue<T>::isEmpty() const
return !numItems > 0;
//clear
template <class T>
void DynamicQueue<T>::clear()
T value;
while (!isEmpty())
dequeue(value);
#endif
二叉树.h
#ifndef BINARYTREE_H
#define BINARYTREE_H
#include <iostream>
#include "DynamicQueue.h"
using namespace std;
//BinaryTree Template
template <class T>
class BinaryTree
private:
struct TreeNode
T value; // TThe value in the node
TreeNode* left; //Pointer to the left child node
TreeNode* right; //Pointer to the right child node
;
TreeNode* root; //Pointer to the root node
//Private methods
void insert(TreeNode *&, TreeNode *&);
void destroySubtree(TreeNode *&);
void deleteNode(T, TreeNode *&);
void makeDeletion(TreeNode *&);
void displayInOrder(TreeNode *) const;
void displayPreOrder(TreeNode *) const;
void displayPostOrder(TreeNode *) const;
void loadInQueue(DynamicQueue<T>, TreeNode *);
public:
//Constructor
BinaryTree()
root = nullptr;
//Destructor
~BinaryTree()
destroySubtree(root);
//Binary Tree Operations
void insertNode(T);
bool searchNode(T);
void remove(T);
void displayInOrder() const
displayInOrder(root);
void displayPreOrder() const
displayPreOrder(root);
void diplayPostOrder() const
displayPostOrder(root);
void convertToQueue(DynamicQueue<T> &);
;
//Insert Method
template <class T>
void BinaryTree<T>::insert(TreeNode* &nodePtr, TreeNode* &newNode)
if (nodePtr == nullptr)
nodePtr = newNode; //Insert the node
else if (newNode->value < nodePtr->value)
insert(nodePtr->left, newNode); //Search the left branch
else
insert(nodePtr->right, newNode); //Search the right branch
//insertNode
template <class T>
void BinaryTree<T>::insertNode(T item)
TreeNode* newNode = nullptr;
//Create a new Node and store val in it
newNode = new TreeNode;
newNode->value = item;
newNode->left = newNode->right = nullptr;
//Insert the node
insert(root, newNode);
//DestorySubTree
template <class T>
void BinaryTree<T>::destroySubtree(TreeNode* &nodePtr)
if (nodePtr)
if (nodePtr->left)
destroySubtree(nodePtr->left);
if (nodePtr->right)
destroySubtree(nodePtr->right);
delete nodePtr;
//searchNode
template <class T>
bool BinaryTree<T>::searchNode(T item)
TreeNode* nodePtr = root;
while (nodePtr)
if (nodePtr->value == item)
return true;
else if (item < nodePtr->value)
nodePtr = nodePtr->left;
else
nodePtr = nodePtr->right;
return false;
//remove
template <class T>
void BinaryTree<T>::deleteNode(T item, TreeNode* &nodePtr)
if (item < nodePtr->value)
deleteNode(item, nodePtr->left);
else if (item > nodePtr->value)
deleteNode(item, nodePtr->right);
else
makeDeletion(nodePtr);
template <class T>
void BinaryTree<T>::makeDeletion(TreeNode* &nodePtr)
TreeNode* tempNodePtr = nullptr;
if (nodePtr == nullPtr)
cout << "Cannot delete empty node.\n";
else if (nodePtr->right == nullptr)
tempNodePtr = nodePtr;
nodePtr = nodePtr->left;
delete tempNodePtr;
else if (nodePtr->left == nullptr)
tempNodePtr = nodePtr;
nodePtr = nodePtr->right;
delete tempNodePtr;
else
tempNodePtr = nodePtr->right;
while (tempNodePtr->left)
tempNodePtr = tempNodePtr->left;
tempNodePtr->left = nodePtr->left;
tempNodePtr = nodePtr;
nodePtr = nodePtr->right;
delete tempNodePtr;
//displayInOrder
template <class T>
void BinaryTree<T>::displayInOrder(TreeNode* nodePtr) const
if (nodePtr)
displayInOrder(nodePtr->left);
cout << nodePtr->value << endl;
displayInOrder(nodePtr->right);
//displayPreOrder
template <class T>
void BinaryTree<T>::displayPreOrder(TreeNode* nodePtr) const
if (nodePtr)
cout << nodePtr->value << endl;
displayPreOrder(nodePtr->left);
displayPreOrder(nodePtr->right);
//displayPostOrder
template <class T>
void BinaryTree<T>::displayPostOrder(TreeNode* nodePtr) const
if (nodePtr)
displayPostOrder(nodePtr->left);
displayPostOrder(nodePtr->right);
cout << nodePtr->value << endl;
//ConvertToQueue
template <class T>
void BinaryTree<T>::convertToQueue(DynamicQueue<T> &queue)
queue.clear();
loadInQueue(queue, root);
//LoadInQUEUE
template <class T>
void BinaryTree<T>::loadInQueue(DynamicQueue<T> queue, TreeNode* nodePtr)
if (nodePtr)
loadInQueue(queue, nodePtr->left);
queue.enqueue(nodePtr->value);
loadInQueue(queue, nodePtr->right);
#endif
ConvertBinaryTreeToQueue.cpp
#include "stdio.h"
#include "conio.h"
#include "BinaryTree.h"
#include "DynamicQueue.h"
using namespace std;
void main()
BinaryTree<int> tree;
for (int i = 0; i < 10; i++)
tree.insertNode(i * 5);
DynamicQueue<int> queue;
tree.convertToQueue(queue);
while (!queue.isEmpty())
int value;
queue.dequeue(value);
cout << value << endl;
_getch();
如果有人能帮我解决,或者至少能理解这个问题,我将不胜感激:)
注意:我来自 Java 背景,在尝试做一些在 Java 中有效但在 C++ 中无效的事情之前,我遇到过问题,所以如果这又是问题,我不会感到惊讶,但在这种情况下,我通常会收到更标准化的错误消息。
【问题讨论】:
不要发布图片链接。发布错误消息的文本。您还应该调用调试器并报告导致问题的行。 嗯,问题是它没有给我一条导致问题的行。程序编译,然后当它中断时,它并没有说明确切的位置。 按重试调试应用程序。 我知道,它说它在 DynamicQueue.h 的第 87 行遇到了一个断点,但那里没有断点,DynamicQueue.h 直接来自书中。除此之外,它不会给我一个错误。如果我在断点后点击继续,它只会一直给我同样的两条错误消息。 有东西损坏了堆。这可能是由此队列或碰巧损坏其数据的无关代码引起的。避免这些错误的最简单方法是不使用任何手动内存管理,而仅使用容器和智能指针。也不要假设书本上的代码是好的或正确的。 【参考方案1】:这两个错误都与您的程序尝试访问不允许的内存(不再允许)有关。
在此函数 convertToToQueue
中,您创建一个名为 newQueue
的新 DynamicQueue
,该函数的范围结束时将被销毁:
//ConvertToQueue
template <class T>
void BinaryTree<T>::convertToQueue(DynamicQueue<T> &queue)
DynamicQueue<T> newQueue;
loadInQueue(newQueue, root);
queue = newQueue;
将newQueue
分配给queue
不会达到您的预期。 DynamicQueue
类缺少复制构造函数,因此编译器会尽其所知为您制作一个。它会复制front
、rear
和numItems
的值。
当newQueue
超出范围时,其中的所有QueueNode
对象都将被删除(因为DynamicQueue
的析构函数调用clear();
)。此时queue.front
和queue.end
指向无效内存。
您应该从参数中传入queue
,而不是创建新的DynamicQueue
。如果您想确保queue
仅包含来自BinaryTree
的项目,您可以在调用loadInQueue
之前调用queue.clear();
。
【讨论】:
感谢您的建议。该技巧有助于改进设计,但似乎并没有解决问题。我已经更新了方法,但它似乎给了我同样的问题。编辑:我已经用修复更新了上面的代码。 更新:在考虑到这个新建议进行了一些调整之后,我已经开始工作了。非常感谢!以上是关于调试断言失败!奇怪的问题的主要内容,如果未能解决你的问题,请参考以下文章