调试断言失败!奇怪的问题

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 类缺少复制构造函数,因此编译器会尽其所知为您制作一个。它会复制frontrearnumItems 的值。

newQueue 超出范围时,其中的所有QueueNode 对象都将被删除(因为DynamicQueue 的析构函数调用clear();)。此时queue.frontqueue.end指向无效内存。

您应该从参数中传入queue,而不是创建新的DynamicQueue。如果您想确保queue 仅包含来自BinaryTree 的项目,您可以在调用loadInQueue 之前调用queue.clear();

【讨论】:

感谢您的建议。该技巧有助于改进设计,但似乎并没有解决问题。我已经更新了方法,但它似乎给了我同样的问题。编辑:我已经用修复更新了上面的代码。 更新:在考虑到这个新建议进行了一些调整之后,我已经开始工作了。非常感谢!

以上是关于调试断言失败!奇怪的问题的主要内容,如果未能解决你的问题,请参考以下文章

断言失败第二次添加/删除

未知函数中的断言失败

MSBuild Copy 失败并出现奇怪的错误消息

重新加载节索引时出现奇怪的错误?

我在 Flutter 中遇到了一个问题:在构建 TextField 时抛出了以下断言,它使我遇到了一个奇怪的问题

在 UISegmentedControl 上记录点击在测试期间断言失败