I am currently working on implementing a stack data structure using linked lists in C++. I can compile everything fine up until the point I test my "stack.push" method when I receive a debug assertion failed error that I have no where near enough knowledge as to how to begin to fix it. I just started on here so I cannot post images apparently, but in short it says:
Debug Assertion Failed!
Program...ual studio 2013/....~
File:f:/dd/vctools/crt/crtw32/misc/dbgdel.cpp
Line: 52
Expression:_BLOCK_TYPE_IS_VALID(pHead->nBlockUse
and here are my codes: Stack.h
#ifndef _STACK_H
#define _STACK_H
#include "LList.h"
typedef int ItemType;
class Stack{
public:
Stack();
~Stack();
int size() { return size_; }
void push(ItemType x);
ItemType pop();
ItemType top() { return top_; }
private:
ItemType top_;
void copy(const Stack &source);
int size_;
LList items_;
};
#endif _STACK_H
stack.cpp:
#include "Stack.h"
Stack::Stack()
{
size_ = 0;
ItemType top_ = NULL;
}
void Stack::push(ItemType x)
{
items_.append(x);
size_ += 1;
ItemType top_ = x;
}
ItemType Stack::pop()
{
ItemType top_ = size_ - 1;
size_ -= 1;
return items_.pop();
}
Stack::~Stack()
{
items_.~items_();
}
The error occurs after writing test code that assigns a stack and then tries to push a number onto the stack.
Any help would be appreciated and I apologize if there are any formatting issues with my post.
There are several problems with your code:
Like mentioned in another answer, append will add the item at the end of the list (i.e., at the bottom from stack perspective) instead of at the top.
Your usage of top is inconsistent, you should decide what it means. Classically, top would hold or point to the last inserted element.
You have syntax issues and you're actually redeclaring a new local variable for top instead of using the class member.
You have memory corruption in the destructor when you explicitly call the contained list destructor.
You are a bit confused as to what append does. Append places a value (in this case an ItemType x) to the end of your stack, not the front. You then assign the top of the stack to the end of the stack, and you lose the pointers to the head of your list.
In fact, there are multiple things wrong now that I look at the rest of your code. I think you lack an understanding of what Linked Lists do, and you should go and read them yourself instead of me just dropping working code in my answer.
Related
I wrote a program to create a linked list, and I got undefined behavior (or I assume I did, given the program just stopped without any error) when I increased the size of the list to a certain degree and, critically, attempted to delete it (through ending its scope). A basic version of the code is below:
#include <iostream>
#include <memory>
template<typename T> struct Nodeptr;
template<class T>
struct Node {
Nodeptr<T> next;
T data;
Node(const T& data) : data(data) { }
};
template<class T>
struct Nodeptr : public std::shared_ptr<Node<T>> {
Nodeptr() : std::shared_ptr<Node<T>>(nullptr) { }
Nodeptr(const T& data) : std::shared_ptr<Node<T>>(new Node<T>(data)) { }
};
template<class T>
struct LinkedList {
Nodeptr<T> head;
void prepend(const T& data) {
auto new_head = Nodeptr<T>(data);
new_head->next = head;
head = new_head;
}
};
int main() {
int iterations = 10000;
{
LinkedList<float> ls;
std::cout << "START\n";
for(float k = 0.0f; k < iterations; k++) {
ls.prepend(k);
}
std::cout << "COMPLETE\n";
}
std::cout << "DONE\n";
return 0;
}
Right now, when the code is run, START and COMPLETE are printed, while DONE is not. The program exits prior without an error (for some reason).
When I decrease the variable to, say, 5000 instead of 10000, it works just fine and DONE is printed. When I delete the curly braces around the LinkedList declaration/testing block (taking it out its smaller scope, causing it NOT to be deleted before DONE is printed), then everything works fine and DONE is printed. Therefore, the error must be arising because of the deletion process, and specifically because of the volume of things being deleted. There is, however, no error message telling me that there is no more space left in the heap, and 10000 floats seems like awfully little to be filling up the heap anyhow. Any help would be appreciated!
Solved! It now works directly off of heap pointers, and I changed Node's destructor to prevent recursive calls to it:
~Node() {
if(!next) return;
Node* ptr = next;
Node* temp = nullptr;
while(ptr) {
temp = ptr->next;
ptr->next = nullptr;
delete ptr;
ptr = temp;
}
}
It is a stack overflow caused by recursive destructor calls.
This is a common issue with smart pointers one should be aware of when writing any deeply-nested data structure.
You need to an explicit destructor for Node removing elements iteratively by reseting the smart pointers starting from the tail of the list. Also follow the rule-of-3/5 and do the same for all other operations that might destroy nodes recursively as well.
Because this is essentially rewriting all object destruction it does however make use of smart pointers in the first place somewhat questionable, although there is still some benefit in preventing double delete (and leak) mistakes. Therefore it is common to simply not use smart pointers in such a situation at all and instead fall back to raw pointers and manual lifetime management for the data structure's nodes.
Also, there is no need to use std::shared_ptr here in any case. There is only one owner per node. It should be std::unique_ptr. std::shared_ptr has a very significant performance impact and also has the issue of potentially causing leaks if circular references are formed (whether intentionally or not).
I also don't see any point in having Nodeptr as a separate class. It seems to be used to just be an alias for std::make_shared<Node>, which can be achieved by just using a function instead. Especially inheriting from a standard library smart pointer seems dubious. If at all I would use composition instead.
All,
I asked a question last week and I thank you for your tolerance in answering. I'm overall an inexperienced coder but have dabbled most of my life. This is the hardest language/class I've ever taken and it's driving me nuts that I can't get some of these concepts. I've done quite a bit of googling and found some helpful things but never something quite similar enough to fix what I've run into.
ALSO: I am not that familiar with the SO interface, so wasn't sure last time how to 'mark' an answer as the best to give credit to those who helped. I didn't see a way to respond to other smaller comments. A lot in here, but I want to do the right thing for you folks taking the time to help others.
The assignment is to create a queue class with five files described as follows:
QueueItem.h contains the class definition for QueueItem
QueueItem.cpp contains the member function implementations for QueueItem.
Queue.h contains the class definition for Queue.
Queue.cpp contains the member function implementations for Queue.
main.cpp contains the main() test function.
Queue.h
#pragma once
#include "QueueItem.h"
class Queue {
public:
Queue(); // ctor inits a new empty Queue
~Queue(); // dtor erases any remaining QueueItems
void addItem(const char* pData);
void removeItem();
void print();
void erase();
private:
QueueItem* _pHead; // always points to first QueueItem in the list
QueueItem* _pTail; // always points to the last QueueItem in the list
int _itemCounter; // always increasing for a unique id to assign to each new QueueItem
};
In Queue.cpp below, there are two places where I think the code should either be _pTail->_pNext or _pTail._pNext. If it's the ->, then I get C++ member (declared at line 21 of) is inaccessible but using the . gives C++ expression must have class type. This is definitely one of the places where I think it's a conceptual thing I'm not understanding because I think it should be the -> but have no idea how to make that accessible.
Queue.cpp
#include "Queue.h"
#include "QueueItem.h"
#include <iostream>
using namespace std;
void Queue::addItem(const char* pData) {
// dynamically create and init a new QueueItem object
QueueItem* pItem = new QueueItem(pData, ++_itemCounter);
if (0 == _pHead) // check for empty queue
_pHead = _pTail = pItem;
else {
// link new item onto tail of list using _pTail pointer
_pTail->_pNext = pItem; // links the current pTail to the new pItem
_pTail = pItem; // move the pTail to the new item
}
}
void Queue::removeItem() {
// check for empty queue
if (0 == _pHead)
{ // if empty, nothing to do
}
else
{
// pop top item off
QueueItem* popped = _pHead; // create popped to hold value of _pHead
_pHead = popped->_pNext; // Move the pHead to the next in queue
delete popped; // delete the popped value
--_itemCounter; // decrement counter
}
}
QueueItem.h
#pragma once
#include "Queue.h"
class QueueItem {
public:
QueueItem(const char* pData, int id); // ctor
void setNext(QueueItem* pItem);
QueueItem* getNext() const;
int getId() const;
const char* getData() const;
private:
char _data[30]; // data value (null terminated character string)
const int _itemId; // unique id for item in queue
QueueItem* _pNext; // next item in queue
};
In QueueItem.cpp below, the ctor is not right. The error C++ no instance of overloaded function matches the specified type comes up and I'm not sure why. It seems like the call matches the definition?
QueueItem.cpp
#include "QueueItem.h"
#include <cstring>
#include <string>
QueueItem::QueueItem(char* pData, int id) // ctor
: _itemId{ id } // Initialization list
{
strcpy_s(_data, pData);
_pNext = NULL;
}
void QueueItem::setNext(QueueItem* pItem)
{
_pNext = pItem;
}
QueueItem* QueueItem::getNext() const
{
return _pNext;
}
int QueueItem::getId() const
{
return _itemId;
}
const char* QueueItem::getData() const
{
return _data;
}
main.cpp
#include <iostream>
#include <conio.h>
#include "Queue.h"
using namespace std;
// note - you may need to change the definition of the main function to
// be consistent with what your C++ compiler expects.
int main() {
char anykey;
Queue myQueue;
myQueue.removeItem();
myQueue.addItem("red");
myQueue.addItem("green");
myQueue.addItem("blue");
myQueue.addItem("orange");
myQueue.print(); // print contents of queue (item ID and data)
myQueue.removeItem();
myQueue.removeItem();
myQueue.removeItem();
myQueue.removeItem();
myQueue.print();
myQueue.erase();
myQueue.addItem("olive");
myQueue.addItem("mauve");
myQueue.addItem("purple");
myQueue.print();
myQueue.erase();
myQueue.print();
cout << "Press any key...";
anykey = getch();
return 0;
}
Let's walk through this in order.
Queue.h
#pragma once
#include "QueueItem.h"
You don't actually use the definition of the QueueItem in this header, you only mention pointers to it. To have a pointer to a type (without ever dereferencing it - in the header, that is) - we just need to know the type exists.
So, you can replace the include with the forward declaration
class QueueItem;
And break the cycle between the two header files. (You will now need to include QueueItem.h in Queue.cpp though, because you actually do use it there).
You actually don't need to include Queue.h in QueueItem.h either, because it isn't used at all.
In Queue.cpp below, there are two places where I think the code should either be _pTail->_pNext or _pTail._pNext.
Yep, your first thought was correct.
If it's the ->, then I get C++ member (declared at line 21 of) is inaccessible
The word "inaccessible" tells us that the problem with _pTail->_pNext is that QueueItem::_pNext is declared private. Only methods of the QueueItem class (or friends) itself are allowed to access its private members.
You could add a friend declaration to QueueItem to let Queue have privileged access to its private parts. But, as you already have a public accessor, you can just write _pTail->getNext() instead.
but using the . gives C++ expression must have class type.
This is because only class (and struct, and union) objects have members. You have a pointer to a class object, so -> is the right choice. If it helps to remember, p->member is essentially the same as (*p).member ... it's just nicer to type.
In QueueItem.cpp below, the ctor is not right. The error C++ no instance of overloaded function matches the specified type comes up and I'm not sure why. It seems like the call matches the definition?
These two are not the same:
QueueItem(const char* pData, int id);
QueueItem::QueueItem( char* pData, int id) { ... }
I try to just copy & paste lines like this where possible - there's no benefit in doing more typing, with more opportunity for mistakes, and it's sometimes hard to see these simple errors when you know what you intended to write.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
Here is the Program
#include <iostream>
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
using namespace std;
struct node
{
int data;
node *next;
};
typedef node *list;
bool create(list header){
return header==NULL;
}
void insert_begining(list header,int item){
node*p;
p=new(node);
if (p=NULL)
{
return;
}
p->data=item;
p->next=header;
header=p;
}
void insert_end(list header,int item){
list p,q;
p=new(node);
p->data=item;
p->next=NULL;
if (header==NULL)
{
header=p;
}
else
{
q=header;
while(q->next!=NULL){
q=q->next;
}
q->next=p;
}
}
void print_list(list header){
node* p;
p=header;
while(p->next!=NULL){
cout<<p->data<<endl;
p=p->next;
}
}
int main(){
list header;
create(header);
insert_end(header,500);
insert_end(header,600);
insert_end(header,4);
insert_end(header,6);
print_list(header);
return 0;
}
i run the program and it shows
Process returned -1073741819 (0xC0000005) execution time : 6.720 s
i really don't know why.I think that the syntax is right
pleases check the program above and tell me what to do.
i am a beginner and i really don't know much about linked lists
First, you need to understand pass-by-value vs pass-by-reference. In the former case a copy of the var is passed and in the latter the actual var is passed. Ex:
void f1(int x) { // Pass by value
x = 1;
}
void f2(int& x) { // Pass by reference
x = 2;
}
int main() {
int y = 0;
f1(y);
// y is still 0
f2(y);
// y is now 2
}
In your program, you pass header by value:
void insert_begining(list header,int item){
// ....
header=p; // Only modifying the local var!
}
Some things I would do:
First, get rid of that typedef. This is C++ but you are not using classes, so I assume you haven't learned them yet. Instead, create a linked list struct:
struct node
{
int data;
node *next;
};
struct linked_list {
struct node *head;
linked_list() : head(nullptr) {} // ctor
};
No more typedef needed, and now you can easily pass by reference. Ex:
void insert_begining(linked_list& list, int item){
// removed for brevity
p->next = list.head;
list.head = p;
}
When you declare the header variable it is not initialized to NULL. In C++
variables are usually not initialized by the compiler upon declaration.
So when you make the call
insert_end(header, 500);
inside the function the else block is executed since header is not NULL but a garbage value. The culprit here is:
while(q->next!=NULL);
You cannot evaluate q->next since q points to a random memory location and hence the segfault. You need to assign to a variable before accessing it.
So in you main function add this:
list header = NULL;
Apart for this your might want to check BLUPIX's comments about other problems.
Also use nullptr instead of NULL if the compiler supports C++11
I am in process of learning c++. I am working on creating a linkedlist data structure. One of the functions that displays the values of nodes in the structure does not work. For some reason the while loop that traverses through nodes doesn't work in the display function, hence I can't see the values in those nodes. Does anyone see what the problem is? I've been staring at the code for a while and not sure what is wrong here.
Thanks for your help in advance.
Header:
// linklist.h
// class definitions
#ifndef LINKLIST_H
#define LINKLIST_H
class linklist
{
private:
// structure containing a data part and link part
struct node
{
int data;
node *link;
}*p;
public:
linklist();
void append(int num);
void addatbeg(int num);
void addafter(int loc, int num);
void display();
int count();
void del(int num);
~linklist();
};
#endif
.cpp file
// LinkedListLecture.cpp
// Class LinkedList implementation
#include"linklist.h"
#include<iostream>
using namespace std;
// initializes data member
linklist::linklist()
{
p =NULL;
}
// adds a node at the end of a linked list
void linklist::append(int num)
{
node *temp, *r;
// if the list is empty, create first node
if(p==NULL)
{
temp = new node;
temp->data = num;
temp->link = NULL;
}
else
{
// go to last node
temp = p;
while(temp->link!=NULL)
temp = temp->link;
// add node at the end
r = new node;
r->data=num;
r->link=NULL;
temp->link=r;
}
}
// displays the contents of the linked list
void linklist::display()
{
node *temp = p;
cout<< endl;
// traverse the entire linked list
while(temp!=NULL) // DEBUG: the loop doesn't work
{
cout<<temp->data<<" ";
temp = temp->link;
}
void main()
{
linklist l;
l.append(14);
l.append(30);
l.append(25);
l.append(42);
l.append(17);
cout<<"Elements in the linked list:";
l.display(); // this function doesn't work
system("PAUSE");
}
You never set p to a non NULL value.
if(p==NULL)
{
p = new node;
p->data = num;
p->link = NULL;
}
I think GWW has highlighted the issue, but part of learning to program it to learn how to identify the mistakes.
If you do something and don't get the expected result you could:
Use the visual c++ debugger to step through and see the values of your variables.
Put in log lines to report information you think is important
inspect the code - if you think something is right but it doesn't work, then go to an earlier step and check it does the right thing.
Add unit tests, or follow design by contract adding pre/post conditions and class invariants.
Learning to program C++ by writing a linked list is like learning math by adding 1 + 1. It is old fashioned thinking, slow and mostly boring without having any context.
Math isn't calculating, like C++ programming isn't pointer manipulation. At some stage you might need to know about it, but your better off learning other important things like stl and boost.
If it was understood that append() ment create something, find the end of the list, add it. you could then see that in you append function you have create something mixed uyp with move to the end of the list, but you never add it.
DEAR All;
Hi, I'm just beginner to C++;
Please help me to understand:
What functions should be in the Linked list class ?
I think there should be overloaded operators << and >>;
Please help me to improve the code (style, errors, etc,)
Thanks for advance. Igal.
Edit:
This is only first stage, the next one will be (hopefully) with templates.
Please review the small code for the integer List (enclosed MyNODE.h and ListDriver1.cpp);
MyNODE.h
// This is my first attempt to write linked list. Igal Spector, June 2010.
#include <iostream.h>
#include <assert.h>
//Forward Declaration of the classes:
class ListNode;
class TheLinkedlist;
// Definition of the node (WITH IMPLEMENTATION !!!, without test drive):
class ListNode{
friend class TheLinkedlist;
public:
// constructor:
ListNode(const int& value, ListNode *next= 0);
// note: no destructor, as this handled by TheLinkedList class.
// accessor: return data in the node.
// int Show() const {return theData;}
private:
int theData; //the Data
ListNode* theNext; //points to the next node in the list.
};
//Implementations:
//constructor:
inline ListNode::ListNode(const int &value,ListNode *next)
:theData(value),theNext(next){}
//end of ListNode class, now for the LL class:
class TheLinkedlist
{
public:
//constructors:
TheLinkedlist();
virtual ~TheLinkedlist();
// Accessors:
void InsertAtFront(const &);
void AppendAtBack(const &);
// void InOrderInsert(const &);
bool IsEmpty()const;//predicate function
void Print() const;
private:
ListNode * Head; //pointer to first node
ListNode * Tail; //pointer to last node.
};
//Implementation:
//Default constructor
inline TheLinkedlist::TheLinkedlist():Head(0),Tail(0) {}
//Destructor
inline TheLinkedlist::~TheLinkedlist(){
if(!IsEmpty()){ //list is not empty
cout<<"\n\tDestroying Nodes"<<endl;
ListNode *currentPointer=Head, *tempPtr;
while(currentPointer != 0){ //Delete remaining Nodes.
tempPtr=currentPointer;
cout<<"The node: "<<tempPtr->theData <<" is Destroyed."<<endl<<endl;
currentPointer=currentPointer->theNext;
delete tempPtr;
}
Head=Tail = 0; //don't forget this, as it may be checked one day.
}
}
//Insert the Node to the beginning of the list:
void TheLinkedlist::InsertAtFront(const int& value){
ListNode *newPtr = new ListNode(value,Head);
assert(newPtr!=0);
if(IsEmpty()) //list is empty
Head = Tail = newPtr;
else { //list is NOT empty
newPtr->theNext = Head;
Head = newPtr;
}
}
//Insert the Node to the beginning of the list:
void TheLinkedlist::AppendAtBack(const int& value){
ListNode *newPtr = new ListNode(value, NULL);
assert(newPtr!=0);
if(IsEmpty()) //list is empty
Head = Tail = newPtr;
else { //list is NOT empty
Tail->theNext = newPtr;
Tail = newPtr;
}
}
//is the list empty?
inline bool TheLinkedlist::IsEmpty() const
{ return (Head == 0); }
// Display the contents of the list
void TheLinkedlist::Print()const{
if ( IsEmpty() ){
cout << "\n\t The list is empty!!"<<endl;
return;
}
ListNode *tempPTR = Head;
cout<<"\n\t The List is: ";
while ( tempPTR != 0 ){
cout<< tempPTR->theData <<" ";
tempPTR = tempPTR->theNext;
}
cout<<endl<<endl;
}
//////////////////////////////////////
The test Driver:
//Driver test for integer Linked List.
#include <iostream.h>
#include "MyNODE.h"
// main Driver
int main(){
cout<< "\n\t This is the test for integer LinkedList."<<endl;
const int arraySize=11,
ARRAY[arraySize]={44,77,88,99,11,2,22,204,50,58,12};
cout << "\n\tThe array is: "; //print the numbers.
for (int i=0;i<arraySize; i++)
cout<<ARRAY[i]<<", ";
TheLinkedlist list; //declare the list
for(int index=0;index<arraySize;index++)
list.AppendAtBack( ARRAY[index] );//create the list
cout<<endl<<endl;
list.Print(); //print the list
return 0; //end of the program.
}
What functions should be in the Linked list class ?
That depends on what you need to do with it. At the very least, one should probably be able to add elements to it, and to look at the elements in the list.
(This is common sense. Because if you can't modify or read your list in any way, what could it ever be used for?)
I think there should be overloaded operators << and >>;
Why? What would they do? I suppose you mean operator << to do insertion, similar to how objects are inserted into C++ IO streams; but what exactly should operator >> do? Extraction/removal of elements of some sort? If you implement insertion and extraction (?) in this manner, probably noone will be able to understand your linked list class. A linked list is not an IO stream. (Those operators with IO streams were chosen for brevity.)
I would advise you against operator overloading if the meaning of the operation is not clear. I would suggest you name your operations more explicitly, e.g. by providing methods add and remove (I'm still guessing at the meaning of the latter operation >> btw.).
Please help me to improve the code (style, errors, etc,)
I don't want to make this the main point on my answer, so just very briefly off the top of my head, some issues:
You should #include <iostream> instead of #include <iostream.h>, and then either add a using namespace std; or write (e.g.) std::cout instead of cout.
Try to get rid of the friend. You should be able to design your classes in a way that doesn't require this. friend is easily misused to get around proper encapsulation. But encapsulation is something you should definitely think about in OOP.
Though that's not an advice to give to a C++ beginner, if you made your linked list class into a template class, it could store different values than just ints. Just take this as a hint for future improvements.
And finally:
Just use the STL ("Standard Template Library") containers which are included in the C++ standard library. I know that "rolling your own" helps understanding how these data structures work, but be aware that the C++ standard library already includes a solid and efficient set of data containers.
0 should be NULL
inline only in the case that you don't care that your code will be public, usually implementation puts in separate file Mylist.cpp file.
Why your destructor virtual, do you have inheritance ?
You can just define struct node instead separate class its better define your list for practice like in stl. http://www.sgi.com/tech/stl/List.html http://www.cplusplus.com/reference/stl/list/
In C++ common to use vector vs linked list in Java
http://www.yolinux.com/TUTORIALS/LinuxTutorialC++STL.html