[英]C++ Debug Assertion Failed
I've written my own list class for practice, here it is: 我已经编写了自己的列表类进行练习,这里是:
#pragma once
#include <iostream>
using namespace std;
// A linked node structure.
template <typename T>
struct LinkedNode
{
T data;
LinkedNode<T>* next;
LinkedNode<T>* prev;
};
// Class linked list.
template <typename T>
class LinkedList
{
public:
// Constructor
LinkedList()
{
mFirst = 0;
mLast = 0;
}
LinkedList(const LinkedList& rhs)
{
mFirst = 0;
mLast = 0;
// Get a pointer to the first node of rhs.
LinkedNode<T>* current = rhs.mFirst;
// While not at the end of the rhs linked list.
while( current != 0 )
{
insertLast( current->data );
current = current->next;
}
}
// Destructor
~LinkedList()
{
destroy();
}
// Overload
LinkedList& operator=(const LinkedList& rhs)
{
// Check for self assignment
if ( this == &rhs )
return *this;
// Get a pointer to the first node of rhs.
LinkedNode<T>* current = rhs.mFirst;
// While not at the end of the rhs linked list.
while( current != 0 )
{
insertLast( current->data );
current = current->next;
}
// Chain assignments a = b = c = d
return *this;
}
// Check if list is empty.
bool isEmpty()
{
if( mFirst == 0 && mLast == 0 )
return true;
else
return false;
}
// Return first and last nodes.
LinkedNode<T>* getFirst() { return mFirst; };
LinkedNode<T>* getLast() { return mLast; };
void insertFirst(T tData);
void insertLast(T tData);
bool insertAfter(T tKey, T tData);
void removeFirst();
void removeLast();
void remove(T removalCandidate);
void destroy();
private:
LinkedNode<T>* mFirst;
LinkedNode<T>* mLast;
};
template <typename T>
bool LinkedList<T>::insertAfter(T tKey, T tData)
{
if( isEmpty() ) return false;
// Get a pointer to the front of the list
LinkedNode<T>* current = mFirst;
// Loop until we find the tKey (the value of the node to insert after)
while( current->data != tKey )
{
// Hop to the next node.
current = current->next;
// Test if we reached the end, if we did we didn't find the node to insert after (tKey)
if( current == 0 )
return false;
}
// Allocate memory for the new node to insert.
LinkedNode<T>* newNode = new LinkedNode<T>();
newNode->data = tData;
// Special case: Are we inserting after the last node?
if( current == mLast )
{
newNode->next = 0;
mLast = newNode;
}
// No, else link in new node after the current node.
else
{
newNode->next = current->next;
newNode->next->prev = newNode;
}
newNode->prev = current;
current->next = newNode;
return true;
}
template <typename T>
void LinkedList<T>::insertFirst(T tData)
{
LinkedNode<T>* newNode = new LinkedNode<T>();
newNode->data = tData;
// If the list is empty, then this is the first and last node and doesn't have a previous pointer.
if( isEmpty() )
mLast = newNode;
// If the list is not empty, the new node becomes the previous node of the current first node.
else
mFirst->prev = newNode;
// The new node's next pointer is the old first pointer. May be null if this is the first node being added to the list.
newNode->next = mFirst;
//The new node becomes the first node.
mFirst = newNode;
}
template <typename T>
void LinkedList<T>::insertLast(T tData)
{
LinkedNode<T>* newNode = new LinkedNode<T>();
newNode->data = tData;
if( isEmpty() )
mFirst = newNode;
else
mLast->next = newNode;
newNode->prev = mLast;
mLast = newNode;
}
template <typename T>
void LinkedList<T>::removeFirst()
{
if( !isEmpty() )
{
LinkedNode<T>* current = mFirst;
if( mFirst == mLast )
{
mFirst->next = 0;
mLast->prev = 0;
}
else
{
mFirst = current->next;
mFirst->prev = 0;
}
delete current;
current = 0;
}
}
template <typename T>
void LinkedList<T>::removeLast()
{
if( !isEmpty() )
{
LinkedNode<T>* current = mLast;
if( mFirst == mLast )
{
mFirst = 0;
mLast = 0;
}
else
{
mLast = current->prev;
mLast->next = 0;
}
delete current;
current = 0;
}
}
template <typename T>
void LinkedList<T>::remove(T removalCandidate)
{
LinkedNode<T>* current = mFirst;
if( isEmpty() )
{
cout << "List is empty!" << endl;
}
else
{
while( current->data != removalCandidate )
{
if( current->data == removalCandidate )
{
break;
}
current = current->next;
}
}
if( current == mFirst )
removeFirst();
else if ( current == mLast )
removeLast();
else
{
// Create two linked nodes to access the next and prev nodes.
LinkedNode<T>* left = current->prev;
LinkedNode<T>* right = current->next;
left->next = right;
right->prev = left;
}
delete current;
current = 0;
}
template <typename T>
void LinkedList<T>::destroy()
{
// Is there at least one node in the list?
if( mFirst != 0 )
{
// Get a pointer to the first node.
LinkedNode<T>* current = mFirst;
// Loop until we reach the end of list.
while( current != 0 )
{
// Save the current node.
LinkedNode<T>* oldNode = current;
// Move to next node.
current = current->next;
// Delete saved node.
delete oldNode;
oldNode = 0;
}
}
mFirst = 0;
}
Then I have also written a stack and queue class, and I test them both to see whether a string is a palindrome. 然后,我还编写了一个堆栈和队列类,并对它们都进行了测试,以查看字符串是否是回文。 That all works. 一切正常。 However when it runs the destroy method in the list class, it throws a: block type is valid(pHead->nBlockUse) error on the 但是,当它在list类中运行destroy方法时,它将在以下位置抛出一个:块类型有效(pHead-> nBlockUse)错误。
delete oldNode;
line. 线。
Queue code: 队列代码:
#pragma once
#include <iostream>
#include "LinkedList.h"
#include <cassert>
template <typename T>
class Queue
{
public:
Queue(){};
~Queue()
{
mList.destroy();
}
T& getFirst()
{
assert( !isEmpty() );
return mList.getFirst()->data;
}
bool isEmpty( void )
{
return mList.isEmpty();
}
void push( T newElement )
{
mList.insertLast( newElement );
}
void pop()
{
mList.removeFirst();
}
private:
LinkedList<T> mList;
};
Stack code: 堆栈代码:
#pragma once
#include <iostream>
#include "LinkedList.h"
#include <cassert>
template <typename T>
class Stack
{
public:
Stack(){};
~Stack()
{
mList.destroy();
}
T& getTopItem()
{
// Throw error if list is empty.
assert( !isEmpty() );
return mList.getLast()->data;
}
bool isEmpty( void )
{
return mList.isEmpty();
}
void push( T newElement )
{
mList.insertLast( newElement );
}
void pop()
{
mList.removeLast();
}
private:
LinkedList<T> mList;
};
Main code: 主要代码:
#include "Stack.h"
#include "Queue.h"
#include <iostream>
#include <string>
using namespace std;
int main()
{
Stack<char> strStack;
Queue<char> strQueue;
cout << "Enter a string: ";
string input = "";
getline(cin, input);
for( unsigned int i = 0; i < input.length(); ++i )
{
strStack.push( input[i] );
strQueue.push( input[i] );
}
bool isPalindrome = true;
// FIX PALINDROME AND ASSERTION FAIL
for( unsigned int j = 0; j < input.length(); ++j )
{
if( strStack.getTopItem() != strQueue.getFirst() )
{
isPalindrome = false;
break; // Exit for loop early.
}
// Get rid of next element out.
strStack.pop();
strQueue.pop();
}
cout << input << " is palindrome: " << isPalindrome << endl;
}
I'm not sure why, any help would be appreciated. 我不确定为什么,任何帮助将不胜感激。
The problem is in the removeFirst
function: When you remove the last node in the list (ie mFirst == mLast
is true
) you set the node link pointers to 0
, and then you delete the node. 问题出在removeFirst
函数中:删除列表中的最后一个节点(即mFirst == mLast
为true
)时,请将节点链接指针设置为0
,然后删除该节点。 Now both mFirst
and mLast
points to a deleted node! 现在, mFirst
和mLast
指向已删除的节点!
Instead of setting the next
and prev
links to 0
, you should set mFirst
and mLast
to 0
. 不要将next
和prev
链接设置为0
,而应将mFirst
和mLast
设置为0
。 Just like you already do in removeLast
. 就像您已经在removeLast
所做的一样。
Because you are not setting mFirst to NULL (0) right before the destroy() method returns. 因为您没有在destroy()方法返回之前将mFirst设置为NULL(0)。 If you call destroy() more than once, you'll hit this kind of crt assertion as a result of attempting to delete a pointer twice. 如果您多次调用destroy(),则由于尝试两次删除指针,您将遇到这种crt断言。 The queue class calls mList.destroy in its destructor, but the destructor of mList will call destroy again. 队列类在其析构函数中调用mList.destroy,但是mList的析构函数将再次调用destroy。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.