I am writing a program to implement a stack which works like a real world stack means it topples when the size of a stack reaches threshold and therefore need to create a new stack for inserting that new element.
Below is my program for this:
#include <iostream>
#include<vector>
#include<stack>
using namespace std;
class stack_of_plates
{
vector<stack<int> > stacks;
unsigned int stack_size;
public:
stack_of_plates(unsigned int size=100)
{
stack_size=size;
}
void push(int data)
{
if(stacks.empty())
{
stack<int> *sptr= new stack<int>; //on debugging Segmentation fault at thisline
stacks.push_back(*sptr);
}
vector<stack<int> >::iterator it=stacks.end();
if(it->size()==stack_size)
{
stack<int> *sptr= new stack<int>; //on debugging Segmentation fault at thisline
stacks.push_back(*sptr);
}
it->push(data);
}
void pop()
{
if(stacks.empty())
{
cout<<"\nEmpty Stack";
return ;
}
vector<stack<int> >::iterator it=stacks.end();
if(it->empty())
{
it--;
}
it->pop();
}
int top()
{
if(stacks.empty())
{
cout<<"\nEmpty Stack";
return 0;
}
vector<stack<int> >::iterator it=stacks.end();
if(it->empty())
{
it--;
}
return it->top();
}
};
int main()
{
stack_of_plates ss;
ss.push(1);
ss.push(2);
cout<<ss.top();
return 0;
}
On compiling it gives no error or warning. However program terminates with unusual error.
On debugging its giving segmentation fault error indicating problem in allocating new stack.
Kindly help me how should i change my code while allocating the new stack. Please help me removing this error.
stacks.end(); refers to the (nonexistent) element after the end of the vector. You can't dereference it; doing so will cause undefined behaviour, possibly a segmentation fault.
It's not quite clear what you're doing there, but if you want an iterator for the last element, then either decrement it:
vector<stack<int> >::iterator it=stacks.end(); // points past the end
--it; // points to last element
or use a reverse iterator (in which case, you use ++ rather than -- to move backwards through the sequence):
vector<stack<int> >::reverse_iterator it=stacks.rbegin();
Adding an element to a vector can invalidate it, so the it->push_back(data) at the end of push() is incorrect. You could avoid using an iterator here:
void push() {
if (stacks.empty() || stacks.back().size()==stack_size) {
// See below for explanation of this change
stacks.push_back(stack<int>());
}
stacks.back().push(data);
}
In pop(), you probably want to remove the last stack if it's empty; otherwise, you'll end up with two empty stacks at the end, and your code will erroneously try to pop from one of those. Again, doing that could cause a segmentation fault or other undefined behavoiur. You probably want something like:
void pop() {
if (stacks.empty()) {
cout<<"\nEmpty Stack";
return ;
}
stacks.back().pop();
if (stacks.back().empty()) {
stacks.pop_back();
}
}
And now we've established an invariant that the last stack is never empty, top can be a bit simpler:
int top() {
if (stacks.empty()) {
cout<<"\nEmpty Stack";
return 0;
}
return stacks.back().top();
}
Also, you usually don't want to create objects using new, especially in a case like this where you're putting a copy of the object into the vector and then discarding the pointer, leaking the allocated memory. You can add an empty stack to the vector like this:
stacks.push_back(stack<int>());
Sometimes (but not in this case) you might want to store pointers to allocated objects in a container; in that case, either remember to delete them when they're removed from the container, or store smart pointers such as std::unique_ptr. But in this case, just store objects.
There are many problems with the code, so it is hard to say which one is the direct cause of your problem. You need the clean them up one by one and then retest. If you still have a problem, post your new code here.
Here is the list:
You have a memory leak from your allocation with new. Since you have a vector of stacks, all you need to do is resize the vector and a new stack will be allocated. So
stacks.resize(stacks.size() + 1);
instead of
stack<int> *sptr= new stack<int>;
stacks.push_back(*sptr);
vector<>.end() returns an iterator that point to an element AFTER the last one, which is why #Joachim suggested that you need to decrement the iterator before you use it.
You have a logical error when you check whether to transfer storage to a new stack - after checking is the size of the last stack is the max, and creating a new one, you keep pushing on the old one.
I hope this helps.
std::stack<int> already has the functionality you show in your example, so there is no need for a std::vector< std::stack<int> >. By just pushing and popping to the std::stack<int> you avoid most of the issues your having in your code. There is no reason to limit std::stack<int> to stack_size.
Next to that, when you need the last entry in a container, use back() instead of end().
Related
#include<iostream>
#include<vector>
using namespace std;
class Stack {
private:
int maxSize;
vector<int> v;
int top;
public:
Stack(int size) {
this->maxSize = size;
this->v.reserve(this->maxSize);
this->top = -1;
}
void push(int j) {
if (!(this->isFull())) {
this->v[++this->top] = j;
} else {
cout << "stack is full"<<endl;
}
}
int pop() {
if (!(this->isEmpty())) {
return this->v[this->top--];
} else {
cout << "\nstack is empty"<<endl;
cout<< "StackOverflow "<<endl;
}
}
int peak() {
return this->v[this->top];
}
bool isEmpty() {
return (this->top == -1);
}
bool isFull() {
return (this->top == this->maxSize - 1);
}
};
int main() {
Stack s(10);
s.push(10);
s.push(20);
cout<<s.pop();
cout<<"\n"<<s.pop();
s.push(40);
cout<<"\n"<<s.pop();
}
How can I make this code more better and reliable for these reasons:
The output of this code is 20 10 40 .
But in the output I want to print "Stack is empty" after every
time the stack is empty after popping out all the elements from the
stack
It fails toprint "Stackis Empty " every time .
You have UB in your code:
this->v[++this->top] = j;
return this->v[this->top--];
ans so on. The fact that you reserved space in a std::vector does not make accessing thous elements legal, you access elements out of bounds. And you overcomplicated your code - std::vector maintains it's size so you do not need index top at all. All you need is push_back() adding element and use back() to access last and then pop_back() to remove it. You can use std::vector>::empty()or std::vector::size() to check if there are elements left.
The specific problem in your code is due to your attempting out of bounds access with a std::vector; the behaviour of which is undefined. Note that reserve does not make that number of elements available for use; only potentially available without a subsequent memory reallocation. If you had used at rather than [] then your C++ standard library would have thrown a runtime error.
std::vector has push_back and a pop_back functions which does allow you to use it to model a stack reasonably effectively.
But, typedef std::stack<int> Stack; in place of all your code is by far the best way.
Don't use C++ standard library container objects to model other containers that are also in the C++ standard library. Container objects are really difficult to write properly; and take a lot of debugging.
The way you programmed it, it only prints "Stack is empty" if the stack is already empty when you call pop, not when it has 1 element and is only empty after calling pop.
Suppose you have 1 element on the stack. So top is 0.
int pop() {
if (!(this->isEmpty())) {
This if evaluatetes to true, and therefore nothing will be printed. This is because isEmpty() evaluates to false with top set to 0.
What you want to do is doing the pop first, and then checking if the stack is empty. On top of checking it at the beginning either way, because you can't pop an empty stack.
Hello I have a problem with pointer on struct in a stack.
I have a stack of struct:
stack<Somethink*> stack1;
And i want to push and pop array of "Somethink"
void Search(Somethink* array_Somethink, int s, int d,) {
stack1.push(&(array_Somethink[s])); //
while (stack1.size() != 0) {
int i = 0;
array_Somethink[i] = *(stack1.pop()); // this return a error
i++;
}
}
I hope someone can give me a tip, how to properly push and pop from this stack
Thank you :D
void Search(Somethink* array_Somethink, int s, int d,) {
stack1.push(&(array_Somethink[s])); //
while (!stack1.empty()) {
int i = 0;
array_Somethink[i] = *(stack1.top());
stack1.pop();
i++;
}
}
My modified code assumes, you have "owning" pointers to the elements on the stack somewhere else. If that is not the case, you would end with memory leaks here, as the pointers in the stack become dangling objects (leaks).
In order to avoid the potential for memory leaks, here, it might be a good idea if you used std::shared_ptr<Somethink> instead of raw pointers. Then, your stack would become a std::stack< std:shared_ptr<Somethink> >.
For details on std::stack operations empty(),pop(),top(), see std::stack in the usual place.
There, you will find explanations such as this:
std::stack::top
C++ Containers library std::stack
reference top();
const_reference top() const;
Returns reference to the top element in the stack. This is the most recently pushed element. This element will be removed on a call to pop(). Effectively calls c.back().
top will return a pointer to the struct and you are trying to assign it to an instance of the struct. Basically you are trying to assign a pointer to Somethink to a position in an array of Somethink's
My assignment is to implement a stack (array-based) with a given capacity that, when attempting to add another element after the stack is full, will grow by a constant value (I used 100).
The problem here I believe lies in my push() function, which adds 100 element to the stack... probably syntactical but I'm not sure at all why my program won't execute.
template<class Type>
class ArrayStack{
enum {default_cap=100};
private:
Type* S; //array storing elements
int CAP; //capacity of stack
int TOP; //top element of stack
public:
ArrayStack(int defc = default_cap); //constructor with default parameter
~ArrayStack(){} //is "delete [] S;" supposed to go in here? not sure
bool isEmpty() const { return (TOP<0); }//is the stack empty?
int size() const { return (TOP+1); }
const Type& top(){ return S[TOP];} //has exception handling, not displayed
Type pop() {--TOP;} //removes top element
//here's the function that concerns me:
//--------------------------------------------
void push (const Type& e){
if(size() == CAP) {
Type* Snew = new Type[CAP+100];
for(int i = 0; i < CAP; i++){
Snew[i] = S[i];
}
delete [] S;
++CAP;
S = Snew;
}
S[++TOP] = e;
}
//--------------------------------------------
//other functions...
};
//constructor:
template<typename T> ArrayStack<T>::ArrayStack(int d)
: S(new T[d]), CAP(d), TOP(-1){}
It's a bit hard to comment since you've only provided partial code, and haven't demonstrated usage (e.g. with a main() function).
However, an obvious problem [which I notice Roger Rowland has identified in his comment too] with the push() function is that it increases allocated size by 100, but only increments CAP. So it will add 100 elements to the array, but only report ability to use the first one added.
The pop() function also discards the top element, and doesn't return it. If the caller ever tries to use the return value from pop() - and users of a stack type do normally expect to be able to use values they pop - the result will be undefined behaviour.
Your destructor definitely needs to use operator delete, unless you clean up dynamically allocated memory in some other way (and you've shown nothing like that). The whole point of operator new is that memory is NOT released until a corresponding operator delete. It will not be cleaned up magically if you forget to do it, and will present a memory leak for (at least) as long as your program runs.
If you want to do things a bit more safely, use a std::vector instead of a pointer (and avoid using operator new directly).
I have the following class, Tuple:
class Tuple {
public:
Tuple(){
}
Tuple(vector<string> newValueList){
this->values = newValueList;
}
~Tuple() {
}
private:
vector<string> values;
}
When I call the destructor method I get a memory leak (using valgrind):
Invalid read of size 8
at 0x40BE66: std::vector<std::string, std::allocator<std::string> >::~vector()
by 0x40BB2D: Tuple::~Tuple()
I am not sure at all why this is happening. I thought that vectors did their own memory management.
Edit:
Here is an example of how I create a Tuple:
Tuple* Tuple::duplicate(string value, int count, bool pull){
Tuple* returnTuple = 0;
vector<string> newValueList;
for (size_t i = 0; i < this->values.size(); i++) {
if (((int)i == count)&&!pull)
continue;
else{
newValueList.push_back(this->values[i]);
}
}
returnTuple = new Tuple(newValueList);
return returnTuple;
}
Ok so I figured out the solution after your comments.
I had a vector<Tuple*> and it was causing memory leaks like crazy. I went through my whole code and changed each instance of Tuple* to just Tuple and made the other necessary changes to make sure my code still worked. After doing that, I had no problems with the destructor for Tuple. Thanks for all your input.
Tuple* Tuple::duplicate(string value, int count, bool pull)
What is use of value?
You are allocating objects dynamically
returnTuple = new Tuple(newValueList);
Vector is being initialized inside Tuple object. There will be no memory leak if you explicitly delete returnTuple somewhere in your code. You will have to keep track of all objects you create dynamically. Or better suggestion is to go for shared_pointers, which will manage memory release.
Also changing Tuple* to Tuple helped because you shifted from dynamic/heap allocation to stack allocation. Destructor will be automatically called once you stack objects go out of scope.
For some reason this isn't working for me. It gives me the vector iterator out of range error.
directory_entry TDE("Path");
vector <directory_entry> Temp;
Temp.push_back(TDE);
User_Data->DPath.insert(User_Data->DPath.begin(), Temp.begin(), Temp.end());
But, this works,
vector <directory_entry> DPath;
directory_entry TDE("Path");
vector <directory_entry> Temp;
Temp.push_back(TDE);
DPath.insert(DPath.begin(), Temp.begin(), Temp.end());
I don't think there is anything wrong with User_Data->DPath because I can push/pop and access elements in it. But for some reason I can't seam to be able to use insert on it without getting out of range errors.
Does anyone know why this might be?
edit: A popup emerges, debug assertion failed. It gives me a line in the vector header file, 1111, and a message "Expression: vector iterator out of range". If I make sure that there is at least one element in User_Data->DPath, and then start at .begin+1, I get "Expression: vector iterator+offset out of range" and it gives me line 157 of the vector header file.
edit: You are all probably right. The g_new0 function does the memory allocation http://developer.gnome.org/glib/2.32/glib-Memory-Allocation.html#g-new0
struct_type : the type of the elements to allocate. n_structs : the
number of elements to allocate. Returns : a pointer to the allocated
memory, cast to a pointer to struct_type.
typedef struct {
vector <directory_entry> DPath;
}State;
static gboolian select_dir (ClutterActor *actor, ClutterEvent *event, g_pointer data){
State *User_Data = (State*)data;
directory_entry Temp(Path);
User_Data->DPath.push_back(Temp);
...
return TRUE;
}
int main( argc, char*argv[]){
State *data = g_new0 (State, 1);
...
g_signal_connect(Cluter_Actor, "button-event", G_CALLBACK(select_dir), data)
...
clutter_main();
g_free(data);
return 0;
}
g_new0 is not a drop-in replacement for new
new does two things: allocates memory for an object, and calls the object's constructor. g_new0 only does the first, allocating memory. You need to call the object's constructor explicitly if you want to use g_new0. This is done using "placement new":
State *data = g_new0 (State, 1);
new (data) State; // placement new - calls the constructor
The reason calling State's constructor is important is that it in turn calls the constructor of the vector<directory_entry> member of State, and this is what initializes the vector. Without initializing the vector properly, you cannot use it.
Note that since you are calling the constructor explicitly, you will also need to call the destructor explicitly before freeing the memory:
data->~State(); // call destructor
g_free(data); // free the memory
Is there a reason you are using g_new0 instead of just new?
State *data = new State;
... // use data
delete data;