When I try to run my code, it show me debug assertion failed .Any one can help me, I am doing stack list,in the header file, I create a struct has three variable, string * s, int numoflength, stackFrame * next
void Stack::push(string& s)
{
StackFramePtr temp_ptr;
temp_ptr=new StackFrame;
temp_ptr->str=new string[s.size()];
(temp_ptr->str)[0]=s;
cout<<temp_ptr->str[0]<<endl;
temp_ptr->num_char=sizeofstring(s);
if(empty())
{
top=temp_ptr;
temp_ptr->next=NULL;
}
else
{
temp_ptr->next=top;
top=temp_ptr;
}
}
this is my code about push I think maybe those errors because of this function.
string Stack::pop()
{
if(empty())
exit(1);
string * name;
StackFramePtr temp;
temp=top;
name=top->str;
top=top->next;
delete temp;
return *name;
}
#include <iostream>
#include "stack.h"
#include <string>
using namespace std;
int main()
{
string str1="to";
string str2="hi";
string str3="food";
string str4="ba";
string str5="ti";
string str6="zhilong";
Stack s;
s.push(str1);
s.push(str2);
s.push(str3);
s.push(str4);
s.push(str5);
s.push(str6);
cout<<s;
system("pause");
return 0;
}
when I try to run this main function it give me debug failure, anyone can help me? thanks very much
class Stack
{
public:
Stack();
//Default Constructor used to create an empty Stack object.
~Stack();
//Destructor for Stack objects.
void push(string& str);
string pop();
bool empty();
//Checks to see if the Stack is empty. Returns true if empty, else returns false.
//Stack remains unchanged after function call.
friend ostream &operator<<(ostream & out_stream, Stack & mystack);
friend istream &operator>>(istream & in_stream, Stack & mystack);
private:
StackFramePtr top; // Points to the top of the stack;
};
ostream &operator<<(ostream & outs, Stack & sta)
{
if(sta.empty())
exit(1);
else
{
StackFramePtr read;
read=sta.top;
while(read!=NULL)
{
outs<<"string = "<<read->str[0]<<endl;
outs<<" number of charcter is" <<read->num_char;
read=read->next;
outs<<endl<<endl;
}
}
return outs;
}
In push you allocate an array of string, and assign that to the str member of Stack. In pop you copy str to name, then delete temp which (I'm assuming) will delete the array that name is now pointing in to. Lastly you dereference this dangling pointer and access memory that has already been freed.
To fix this, declare name as just a string, rather than a pointer to string, then set name=*top->str or name=top->str[0].
Related
I would like to ask 2 question about this code. Where I just try to simulate a stack.
Stack.h
#pragma once
namespace stackandqueue {
class Stack
{
private:
int index;
int *stackdata;
public:
Stack();
~Stack();
void push(int val);
int pop();
int top();
bool isEmpty();
};
}
Stack.cpp
#include "stdafx.h"
#include "Stack.h"
namespace stackandqueue {
Stack::Stack() : index{ 0 }
{
stackdata = new int[index];
}
Stack::~Stack()
{
delete[] &stackdata;
}
void Stack::push(int val) {
stackdata[index] = val;
index++;
}
int Stack::pop() {
int val = stackdata[index];
index--;
return val;
}
int Stack::top() {
return stackdata[index];
}
bool Stack::isEmpty() {
return index == 0;
}
}
Meaning is to let me create
Stack stack;
And then it initilizes a dynamic array with 0 as first index and that let me push, pop, top values.
First question:
Why am I having unresolved symbols for method definitions?
Second question:
About 'stackdata', you find is the right way if I want to declare an "array" with dynamic size for this behaviour?
I'm open for improvements and best practices. Im used to programming languagesbut I've never delved into c ++ and I don't want to have bad practices. So you see I am taking it from the begining.
Thanks.
I post solution reached with your help that maybe helps someone.
class Stack
{
private:
int index;
int* stackdata;
public:
Stack(int size);
~Stack();
void push(int val);
int pop();
int top();
bool isEmpty();
};
Stack::Stack(int size)
: index {0}, stackdata{new int[size]}
{
}
Stack::~Stack()
{
delete[] stackdata;
}
void Stack::push(int val) {
stackdata[index] = val;
index++;
}
int Stack::pop() {
index--;
return stackdata[index];
}
int Stack::top() {
return stackdata[index-1];
}
bool Stack::isEmpty() {
return index == 0;
}
There are several problems with this.
An array, dynamically allocated or otherwise, is not a stack/queue/vector. You're creating literally 0 ints. All of your element accesses after that have undefined behaviour. You need your array to grow, i.e. be a vector, e.g. std::vector.
delete[] &stackdata has the wrong level of indirection. You meant delete[] stackdata. You were trying to delete the pointer which was not dynamically allocated.
You're missing copy/move constructors and copy/move assignment operators so as soon as you transport a Stack anywhere it will explode. (The original instance will do a delete[] on the same pointer that the copied/moved instances will!) Read about the rule of three/five/zero.
Other than that, it looks like a stack.
The problem you don't have here is an undefined reference, which is funny because that's the only one you asked about. :) If you do indeed have such a thing, it's likely a problem with your build system (failing to compile that source file), which we cannot see.
I have defined a stack class containing methods for pushing and popping values onto the stack.
In the tester file (shown below), after running it, an occur occurs & the program crashes. I know this is due to the function f, which creates an error as two pointers are pointing to the same location in memory. If i comment out the line f(s) when the function is called, the pop & push functions work correctly and the output is correct.
To fix this error, I have been asked to ; Create a copy constructor for this class to fix the above problem.
I'm not really familiar with this, so any help would be appreciated in how to do this. Thanks
Main Test file
#include "Stack.h"
#include <iostream>
#include <string>
using namespace std;
void f(Stack &a) {
Stack b = a;
}
int main() {
Stack s(2); //declare a stack object s which can store 2 ints
s.push(4); //add int 4 into stack s
//s = [4]
s.push(13); //add int 13 into stack s
//s = [4,13]
f(s); //calls the function f which takes in parameter Stack a , and sets Stack b = to it.
//error here - as 2 pointers point to the same location in memory !
cout << s.pop() << endl; //print out top element(most recently pushed) element.
//so should output 13
return 0;
}
Header File Code
#ifndef STACK_H
#define STACK_H
class Stack {
public:
//constructor
Stack(int size);
//destructor
~Stack();
//public members (data & functions)
void push(int i);
int pop();
private:
//private members (data & functions)
int stck_size;
int* stck;
int top;
};
#endif
Stack.cpp Code
#include "Stack.h"
#include <iostream>
#include <string>
using namespace std;
Stack::Stack(int size){
stck_size = size;
stck = new int[stck_size];
top = 0;
}
Stack::~Stack() {
delete[] stck;
}
void Stack::push(int i) {
if (top == stck_size) {
cout << "Stack overflow." << endl;
return;
}
stck[top++] = i;
}
int Stack::pop() {
if (top == 0) {
cout << "Stack underflow." << endl;
return 0;
}
top--; //decrement top so it points to the last element istead of the empty space at the top.
return stck[top];
}
Copy constructor here is pretty quick-and dirty:
Stack::Stack(const Stack & src):
stck_size(src.stack_size),
stck(new int[stck_size]),
top(src.top) //Member Initializer List
{
// copy source's stack into this one. Could also use std::copy.
// avoid stuff like memcpy. It works here, but not with anything more
// complicated. memcpy is a habit it's just best not to get into
for (int index = 0; index < top; index++)
{
stck[index] = src.stck[index];
}
}
Now that you have a copy constructor, you're still likely screwed because the Rule of Three has not been satisfied. You need operator=. And this is easy because the copy construct and the copy and swap idiom makes it easy.
Basic form:
TYPE& TYPE::operator=(TYPE rhs) //the object to be copied is passed by value
// the copy constructor makes the copy for us.
{
swap(rhs); // need to implement a swap method. You probably need one
//for sorting anyway, so no loss.
return *this; // return reference to new object
}
Your copy constructor should look like this:
Stack::Stack(const Stack &r) {
stck_size = r.stck_size;
stck = new int[stck_size];
top = r.top;
memcpy(stck, r.stck, top*sizeof (int));
}
i have a program with 3classes.
first one is for defining a node(my node is an array with 9 elements) - 2nd one contains some functions - 3rd is defining a static stack(I have a stack with 100members that each member is an array with 9members)
suppose that in main(), I call one of the functions from 2nd class(for example expand() ). expand function is supposed to push a node into stack(push into UN) and update the stack pointer. After that for example I want to have access to top node of stack and pop that node using main(). but I'm successful. when I watch the UN and top node through debug tool, I see that their amount is being reset after each push(stack doesn't accept new elements). whats wrong?
here is some parts of code that is needed:
#include<iostream>
using namespace std;
#define max 100
class node
{
public:
int node_n[9];
friend class func;
friend class stack;
};
node n;
class node;
class func
{
public:
func();
void expand(node,stack);
friend class stack;
};
class node;
class stack
{
private:
int sp;//stack pointer
public:
node un[max];//saves expanded noded(children)
stack();
int isempty(); //this will show whether stack is empty or not
int isfull(); //this will show whether stack is full or not
void push(node);
node pop();
};
//****************************
stack::stack()
{
sp=-1;
}
//****************************
int stack::isempty()
{
if(sp==-1)
return true;
else
return false;
}
//****************************
int stack::isfull()
{
return sp==max-1;
}
//****************************
node stack::pop() //un=un-[n]
{
for(int k=0;k<=8;k++)
n.node[k]=un[sp].node[k];
sp--;
return n;
}
//****************************
void stack::push(node n ) //un=un+{x1....xn}
{
sp++;
for(int k=0;k<=8;k++)
un[sp].node[k]=n.node[k];
}
//****************************
void func::expand(node n,stack st)
{
if ( n.node_n[0]==0 )
{
if(n.node_n[1]==0)
{
n.node_n[0]=1;
n.node_n[1]=1;
st.push(n);
.
.
.
//******************************
int main()
{
func b;
stack st;
node n2;
node s; //initial state
node g; //goal state
for(int h=0;h<=8;h++)
{
s.node[h]=0;
g.node[h]=1;
}
//n2=s;
st.push(s);
Lable1:
n2=st.pop();
b.expand(n2,st);
goto Lable1;
system("pause");
return(0);
}
This function
void func::expand(node n,stack st)
is taking the st parameter by value, meaning that it has its own copy of st and any changes it makes will only affect that copy.
What you probably want is to pass st by reference, so that the function can make changes to the original passed in object. To do this, change the function declaration and definition to:
void func::expand(node n,stack &st)
I've successfully implemented a recursive PrintList method, so I don't understand why a recursive destructor won't work:
//recursively deleting nodes in a doubly linked list
LinkedList::~LinkedList()
{
if (Head == 0) //base case
{
Tail = 0; //fixing the dangling Tail pointer doesn't seem to fix the error...
return;
}
else
{
Node* temp = Head;
Head = Head->getNext();
cout << "deleting " << temp->getNumber() << endl;
delete temp;
delete this;
}
}
When debugging, I get the _Block_Type_Is_Valid (pHead->nBlockUse) Error after calling the LinkedList destructor, just before the program could finish up "nicely". This is past "return 0;" in main.cpp, and I stepped through the destructor code shown above with no problem, and indeed the destructor gave me all the correct test messages and worked as intended.
Even more frustrating was that I can't locate what caused this error: I tried to "step over" beyond the LinkedList destructor code, but I got the message from VS: "Source Not Available: Source information is missing from the debug information for this module". I was thinking the dangling Tail pointer (which points at a random memory after the destructor executes) might be a problem, so I set "Tail=0;" before returning from the base case, but that doesn't seem to be working.
The only way I can suppress this error is by either:
constructing a LinkedList then simply ending the program without adding any nodes into it (no problem deleting an empty LinkedList), or
making my LinkedList in main dynamically allocated, and ending the program without manually deleting it (skipping the entire LinkedList destructor)
What is the problem here? Help!!
UPDATE: My fantastic CS professor pointed out my problem:
"When the destructor exits and attempts the automatic deallocation of the node, it has already been destroyed by the delete this statement.
When the delete keyword is used, it initiates the destructor and then deallocates the memory."
So like #0x499602D2 pointed out, "delete this" was the problematic line, but it had nothing to do with whether my LinkedList was NEWed and then deleted or statically created at compile time then automatically destroyed. Essentially it was caused by the behavior of the destructor.
The solution therefore is: changing "delete this;" to "this->~LinkedList();"
Only by "this->~LinkedList();" can I make recursive calls to the destructor without really "deleting" the calling object; instead it'll be destroyed when the destructor exits and does the automatic deallocation, avoiding the mistake of deleting it again.
More details:
Here's my implementation of Node (doubly linked). It derives from a singly-linked BaseNode class:
//Specification file for BaseNode class
#ifndef BASENODE_H
#define BASENODE_H
#include <iostream>
class BaseNode
{
protected:
char * name;
int number;
BaseNode * next;
public:
//default constructor
BaseNode();
//overloaded constructor
BaseNode(const char *, int);
//destructor
~BaseNode() {
std::cout << "name is: " << name << '\n';
delete[] name;
}
//getter functions
char * getName() const { return name; }
int getNumber() const { return number; }
BaseNode* getNext() { return next; }
//setter functions
void setNumber(int num){ number = num; };
void setNext(BaseNode* ptr) { next = ptr; }
};
#endif
//Implementation file for BaseNode class
#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS
#endif
#include <cstring>
#include "BaseNode.h"
//default constructor
BaseNode::BaseNode()
{
name = 0;
number = 0;
next = 0;
}
//overloaded constructor
BaseNode::BaseNode(const char * str, int num)
{
roman = new char[strlen(str) + 1]; //set aside one more character for null terminator
strcpy(name, str);
number = num;
}
Then my Node class inherits the BaseNode class:
#ifndef Node_H
#define Node_H
#include "BaseNode.h" //include the base class for inheritance to work
class Node : public BaseNode
{
protected:
Node * prev;
Node * next;
public:
Node() : BaseNode()
{ prev = next = 0; }
Node(const char * namestr, int num) : BaseNode(namestr, num)
{ prev = next = 0; }
//empty destructor; the BaseNode destructor automatically gets called from here and does the job
~Node() { }
//getter functions and setter functions are all inherited from BaseNode, except that....
//the BaseNode version of getNext and setNext won't work for our Node class
Node* getNext() const { return next; }
void setnext(Node* pointer) { next = pointer; }
Node* getPrev() const { return prev; }
void setPrev(Node* pointer) { prev = pointer; }
};
#endif
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
template <class T>
struct TreeNode{
string value;
T key;
TreeNode<T> *LeftChild;
TreeNode<T> *RightChild;
TreeNode (T k,string Val)
{
this->value=Val;
this->key=k;
this->LeftChild=NULL;
this->RightChild=NULL;
}
};
template <class T>
class BinaryTree{
private:
TreeNode<T> *Root;
public:
BinaryTree();
void insertNode();
};
template <class T>
BinaryTree<T>::BinaryTree()
{
Root=NULL;
ifstream fin;
fin.open("names.txt");
string buffer;
T buff;
while (!fin.eof())
{
getline(fin,buffer,'~');
fin>>buff;
cout<<buff<<buffer<<endl;
cout<<"down the tree"<<endl;
TreeNode<T> *temp=Root;
while (temp!=NULL)
{
TreeNode<T> *Right=temp->RightChild;
TreeNode<T> *Left=temp->LeftChild;
if (temp->key>buff)
{
temp=temp->LeftChild;
}
else if (temp->key<buff)
temp=temp->RightChild;
}
cout<<"further down"<<endl;
}
temp->value=buffer;
temp->key=buff;
cout<<"and done!"<<endl;
cout<<"hey"<<endl;
}
fin.close();
}
I am making a binary tree. There are pointers to left and right child in my tree and a key and a string value for each node. In my destructor I am reading from a file and storing the key and value in a node. Every line of the file has the following format:
"M. Ubiquity~ 14100148"
- the Value is the name followed by the key.
Whenever I run this code, I get segmentation fault error but I can't seem to find the fault.
Any hint/help will be appreciated.
You have Root=NULL; and then few lines later TreeNode<T> *temp = Root; so you have temp=NULL.
Obviously the while (temp!=NULL) never executes and after while loop you have temp->value=buffer; which cause segementation fault!
Pointers can only associated with memory addresses, not values. Mainly there are two ways: If you have an automatic variable, you can assign its address to a pointer like this:
int i = 6; //automatic variable
int *pi = &i;
std::cout << pi; // you get the address of pi (hexadecimal number)
std::cout << *pi; // 6
Or you can allocate memory manually. The main thing is if you allocated memory to a variable, you also have to deallocate it or your program will have "memory leak".
int *pi = new int(6);
delete pi;
So if you place new elements in the tree, you have to allocate memory for them, and if you delete an element, you have to destruct with delete. You have to care about not to broke the list.