I'm decently experienced with Python and Java, but I recently decided to learn C++. I decided to make a quick integer stack implementation, but it has a massive memory leak that I can't understand. When I pop the node, it doesn't seem to be releasing the memory even though I explicitly delete the old node upon poping it. When I run it, it uses 150mb of memory, but doesn't release any of it after I empty the stack. I would appreciate any help since this is my first foray into a language without garbage collection. This was compiled with gcc 4.3 on 64-bit Kubuntu.
//a trivial linked list based stack of integers
#include <iostream>
using namespace std;
class Node
{
private:
int num;
Node * next;
public:
Node(int data, Node * next);
int getData();
Node * getNext();
};
Node::Node(int data, Node * next_node)
{
num = data;
next = next_node;
}
inline int Node::getData()
{
return num;
}
inline Node* Node::getNext()
{
return next;
}
class Stack
{
private:
unsigned long int n;
Node * top;
public:
Stack(int first);
Stack();
void push(int data);
int pop();
int peek();
unsigned long int getSize();
void print();
void empty();
};
Stack::Stack(int first)
{
Node first_top (first, NULL);
top = &first_top;
n = 1;
}
Stack::Stack()
{
top = NULL;
n = 0;
}
void Stack::push(int data)
{
Node* old_top = top;
Node* new_top = new Node(data,old_top);
top = new_top;
n++;
}
int Stack::pop()
{
Node* old_top = top;
int ret_num = old_top->getData();
top = old_top->getNext();
delete old_top;
n--;
return ret_num;
}
inline int Stack::peek()
{
return top->getData();
}
inline unsigned long int Stack::getSize()
{
return n;
}
void Stack::print()
{
Node* current = top;
cout << "Stack: [";
for(unsigned long int i = 0; i<n-1; i++)
{
cout << current->getData() << ", ";
current = current->getNext();
}
cout << current->getData() << "]" << endl;
}
void Stack::empty()
{
unsigned long int upper = n;
for(unsigned long int i = 0; i<upper; i++)
{
this->pop();
}
}
Stack createStackRange(int start, int end, int step = 1)
{
Stack stack = Stack();
for(int i = start; i <= end; i+=step)
{
stack.push(i);
}
return stack;
}
int main()
{
Stack s = createStackRange(0,5e6);
cout << s.peek() << endl;
sleep(1);
cout << "emptying" <<endl;
s.empty();
cout << "emptied" <<endl;
cout << "The size of the stack is " << s.getSize()<<endl;
cout << "waiting..." << endl;
sleep(10);
return 0;
}
How do you KNOW the memory isn't being released? The runtime library will manage allocations and may not release the memory back to the OS until the program terminates. If that's the case, the memory will be available for other allocations within your program during its execution.
However.... you seem to have other problems. My C++ is really rusty since I've been doing Java for 15 years, but in your Stack::Stack constructor you're allocating a Node instance on the system stack and then storing a reference to it in your "Stack". That Node instance goes out of scope when the constructor ends, leaving a dangling pointer.
Stack::Stack(int first)
{
Node first_top (first, NULL);
top = &first_top;
n = 1;
}
This is wrong , you cant assign address of a local object to class member( top ) , since local objects get destroyed when function returns.
Create a node on heap rather than stack , do something like this :
Stack::Stack(int first)
{
top = new Node(first, NULL);
n = 1;
}
And Make the concept of link list clear and use pen and paper if you can do so.
Your Stack::Push(int) operation seems buggy check it out what you have forget to do.
My suggestion is try to implement generic stack with the help of template ,so it will work for all data type .
When createStackRange() returns it'll return a copy of the Stack using the compiler-generated copy constructor which just makes a bitwise copy (i.e., it'll copy the pointer to the first node and the size.)
More seriously, you're missing the destructor for the Stack class. Ideally you'd have it walk the list and call delete on each Node. The Stack object created on the processor stack will automatically be cleaned up automatically when main() exits, but without a destructor, the nodes will still be allocated when the program ends. You probably want something like this for it:
Stack::~Stack()
{
while ( top )
{
Next *next = top->getNext();
delete top;
top = next;
}
}
The way to think of it is that the C++ compiler will automatically generate copy constructors and destructors for you, but they're normally shallow. If you need deep behavior you've got to do it implement it yourself somewhere.
After poring over the code, I couldn't find the leak so I compiled it and ran it in a debugger myself. I agree with Jim Garrision - I think you're seeing an artifact of the runtime rather than an actual leak, because I'm not seeing it on my side. The issues pointed out by NickLarsen and smith are both actual issues that you want to correct, but if you trace the code through, neither should actually be causing the problem you describe. The code smith singles out is never called in your example, and the code Nick singles out would cause other issues, but not the one you're seeing.
Creat a stub to test your code and user Memory Analysis tool like "Valgrind". This will find out memory leaks and corruptions for you.
check man-pages for more information.
Note that you should only roll your own stack for educational purposes. For any real code, you should use the stack implementation that comes with the C++ standard library...
Related
I implement the stack with a minimum. In this program, I get an error from valgrind. Something is wrong with the push() and main() functions. When I add delete st; to the push() function, I get even more errors. I check it through valgrind ./a.out. Sorry for the long code. I also wrote the rest of the functions for stack. But there is no error in them, I left those in the code where there may be an error.
#include <cstring>
#include <iostream>
struct Stack {
int data;
int min;
Stack* next;
};
void Push(Stack** top, int n) {
Stack* st = new Stack();
st->data = n;
if (*top == NULL) {
*top = st;
(**top).min = n;
} else {
st->min = ((n <= (**top).min) ? n : (**top).min);
st->next = *top;
*top = st;
}
std::cout << "ok" << std::endl;
}
void Pop(Stack** top) {
if (*top != NULL) {
std::cout << (**top).data << std::endl;
*top = (*top)->next;
} else {
std::cout << "error" << std::endl;
}
}
int main() {
Stack* top = nullptr;
int m;
std::cin >> m;
std::string str;
for (int i = 0; i < m; ++i) {
std::cin >> str;
if (str == "push") {
int value;
std::cin >> value;
Push(&top, value);
}
if (str == "pop") {
Pop(&top);
}
}
delete top;
}
When you just delete top, you destruct it (in your case it's nothing, but you can distract yourself for reading about destructors if interested) and free the dynamic memory allocated for top. However, you actually want to also delete top->next, top->next->next (if present) etc. A hotfix:
while (top) { // same as "while (top != nullptr) {"
Stack* next = top->next; // we can't use `top` after we `delete` it, save `next` beforehand
delete top;
top = next;
}
Now, about more general things. The course teaches you some really old C++ (almost just plain C; even C here is bad though). At the very least, your whole Push() can be replaced (thanks to lvalue references (Type&), std::min and aggregate initialization) with:
void push(Stack*& top, int n) {
top = new Stack{n, std::min(n, top ? top->min : n), top};
std::cout << "ok\n";
}
I'm new to C++ programming. I used to write in Python
Good job. Sadly, such teaching shows C++ as something too old and horrifying.
Edit
here's a new in Push, so there should most likely be a delete in Pop
That's right (thanks to #molbdnilo). You should delete popped elements instead of just leaking them.
So I'm just starting to learn about data structures through a course on Coursera and I learned that it's possible to create a stack data structure by using an array. I was just wondering if what I have written is what a stack is supposed to do.
#include <iostream>
using namespace std;
const int MAX_SIZE = 10000;
class Stack {
public:
Stack();
~Stack();
void push(int n);
void pop();
int top();
bool isEmpty() const;
void print() const;
private:
int* array [MAX_SIZE];
int curNum;
};
Stack::Stack() {
curNum = 0;
}
Stack::~Stack() {
for (int i = 0; i < curNum; ++i)
delete array[i];
}
void Stack::push(int n) {
if (curNum >= MAX_SIZE) {
cout << "reached maximum capacity...can't add an element\n";
return;
}
array[curNum] = new int(n);
curNum++;
}
void Stack::pop() {
delete array[curNum];
curNum--;
}
int Stack::top() {
return *array[curNum];
}
void Stack::print() const{
for (int i = 0; i < curNum; ++i)
cout << *array[i] << endl;
}
bool Stack::isEmpty() const{
return curNum == 0;
}
int main () {
Stack stack;
stack.push(5);
stack.print();
stack.pop();
}
Also, I see that a lot of people don't use dynamic memory allocation for this kind of task. Is there a reason why? It seems like specifying a size for the array at compile time might lead to insufficient memory or over-allocating memory to me
Yes, this is one way to implement a stack. The important thing that defines a stack is LIFO (last in, first out). So as long as you are only adding to and removing from the top, then that is a stack. Think of it as a stack of dishes; if 10 dishes are put one by one into a stack, and then one by one removed from said stack, the first dish put on will also be the last dish removed. You can't remove a dish that's not at the top, as it is covered by all the dishes above it. The same is true with a stack data structure.
So your implementation is indeed a stack.
The stack we use when we want something in reverse order and stack also takes constant time means O(1) time to push and pop means to remove or to add it will work much faster
I am trying to build a huge binary search tree:
class Node
{
public:
int value;
shared_ptr<Node> left;
Node* right;
Node(int v):value(v){}
void addLeft(){
static int i;
shared_ptr<Node> node=make_shared<Node>(i);
left=node;
cout<<i++<<endl;
if(i<60000)
node->addLeft();
}
};
int main(){
shared_ptr<Node>root=make_shared<Node>(9);
root->addLeft();
return 0;
}
I get a seg fault over running this code, in valgrind I have this report:
==17373== Stack overflow in thread #1: can't grow stack to 0xffe801000
Any clue on how to build the BST without overflowing the RAM space?
Any help is much appreciated
Exceeding the stack is not the same as exceeding your RAM. Function calls accumulate on the stack, the problem is you are trying to place 60000 function calls and variables on the stack. Convert your function to a loop and you will be fine. It will even get rid of that terrible static int i.
Here is a version of your function using a for loop with no recursion.
void addLeft()
{
left = std::make_shared<Node>(0);
// tail is the last element to have been added to the tree
std::shared_ptr<Node> tail = left;
std::cout << 0 << std::endl;
// Add nodes from 1 to 60000 inclusively
for (int i = 1; i <= 60000; ++i)
{
std::cout << i << std::endl;
tail->left = std::make_shared<Node>(i);
tail = tail->left;
}
}
I want to make an implementation of stack, I found a working model on the internet, unfortunately it is based on the idea that I know the size of the stack I want to implement right away. What I want to do is be able to add segments to my stack as they are needed, because potential maximum amount of the slots required goes into 10s of thousands and from my understanding making the size set in stone (when all of it is not needed most of the time) is a huge waste of memory and loss of the execution speed of the program. I also do not want to use any complex prewritten functions in my implementation (the functions provided by STL or different libraries such as vector etc.) as I want to understand all of them more by trying to make them myself/with brief help.
struct variabl {
char *given_name;
double value;
};
variabl* variables[50000];
int c = 0;
int end_of_stack = 0;
class Stack
{
private:
int top, length;
char *z;
int index_struc = 0;
public:
Stack(int = 0);
~Stack();
char pop();
void push();
};
Stack::Stack(int size) /*
This is where the problem begins, I want to be able to allocate the size
dynamically.
*/
{
top = -1;
length = size;
z = new char[length];
}
void Stack::push()
{
++top;
z[top] = variables[index_struc]->value;
index_struc++;
}
char Stack::pop()
{
end_of_stack = 0;
if (z == 0 || top == -1)
{
end_of_stack = 1;
return NULL;
}
char top_stack = z[top];
top--;
length--;
return top_stack;
}
Stack::~Stack()
{
delete[] z;
}
I had somewhat of a idea, and tried doing
Stack stackk
//whenever I want to put another thing into stack
stackk.push = new char;
but then I didnt completely understand how will it work for my purpose, I don't think it will be fully accessible with the pop method etc because it will be a set of separate arrays/variables right? I want the implementation to remain reasonably simple so I can understand it.
Change your push function to take a parameter, rather than needing to reference variables.
To handle pushes, start with an initial length of your array z (and change z to a better variable name). When you are pushing a new value, check if the new value will mean that the size of your array is too small (by comparing length and top). If it will exceed the current size, allocate a bigger array and copy the values from z to the new array, free up z, and make z point to the new array.
Here you have a simple implementation without the need of reallocating arrays. It uses the auxiliary class Node, that holds a value, and a pointer to another Node (that is set to NULL to indicate the end of the stack).
main() tests the stack by reading commands of the form
p c: push c to the stack
g: print top of stack and pop
#include <cstdlib>
#include <iostream>
using namespace std;
class Node {
private:
char c;
Node *next;
public:
Node(char cc, Node *nnext){
c = cc;
next = nnext;
}
char getChar(){
return c;
}
Node *getNext(){
return next;
}
~Node(){}
};
class Stack {
private:
Node *start;
public:
Stack(){
start = NULL;
}
void push(char c){
start = new Node(c, start);
}
char pop(){
if(start == NULL){
//Handle error
cerr << "pop on empty stack" << endl;
exit(1);
}
else {
char r = (*start).getChar();
Node* newstart = (*start).getNext();
delete start;
start = newstart;
return r;
}
}
bool empty(){
return start == NULL;
}
};
int main(){
char c, k;
Stack st;
while(cin>>c){
switch(c){
case 'p':
cin >> k;
st.push(k);
break;
case 'g':
cout << st.pop()<<endl;
break;
}
}
return 0;
}
For the life of me, I can't figure out what is going wrong. I know the error is occurring in the function marked displayQueue below, but all the syntax and logic seems correct.
Visual studio is giving me the error: "Unhandled exception at 0x00215A86 in ex11_1.exe: 0xC0000005: Access violation reading location 0xCDCDCDE1." But really, I have no idea what this is referring to...
#include <iostream>
#include <cstdlib>
#include <string>
using namespace std;
struct QueueNode {
string data;
QueueNode *link;
};
typedef QueueNode* QueueNodePtr;
class Queue {
public:
// Constructors/Destructor.
Queue();
Queue(const Queue& aQueue);
// Accessors.
bool empty() const;
void displayQueue ();
// Mutators.
void add(string item);
string remove(); // This should probably be replaced with pop and top - especially for displayQueue... empty() in functions can be replaced with count == 0. Yes, I will do this.
private:
QueueNodePtr front; // Points to head of linked-list queue.
QueueNodePtr back; // Points to tail of linked-list queue.
size_t count;
};
int main () {
Queue myQueue;
myQueue.add("abc");
myQueue.add("def");
myQueue.add("ghi");
myQueue.displayQueue(); // The error is here somewhere. abc is printed and but nothing else.
system("pause");
return 0;
}
Queue::Queue() {
front = NULL;
back = NULL;
count = 0;
}
Queue::Queue(const Queue& aQueue) {
front = aQueue.front;
back = aQueue.back;
count = aQueue.count;
}
bool Queue::empty() const {
if (count == 0) {
return 1;
} else {
return 0;
}
}
void Queue::displayQueue () {
// There is a problem here somewhere...
QueueNodePtr here = front;
for (int i = 0; i < count; i++) {
cout << here->data << endl;
here = here->link;
}
}
void Queue::add(string item) {
QueueNodePtr newNode;
newNode = new QueueNode;
if (count == 0) {
// If inserted in an empty queue, back and front point to same element.
newNode->data = item;
// newNode->link = NULL; // Not sure this part is even necessary.
back = newNode;
front = back;
} else {
// Otherwise, leave front pointer where it's at.
newNode->data = item;
newNode->link = back->link;
back = newNode;
}
count ++;
}
string Queue::remove() {
string returnString;
if (count == 0) {
return returnString;
} else if (count == 1) {
returnString = front->data;
front = NULL;
back = front;
count--;
return returnString;
} else {
returnString = front->data;
front = front->link;
count--;
return returnString;
}
}
EDIT: If anyone can give me any tips on using the debugger to solve problems like this, or give me a link that might explain this it would be greatly appreciated.
The error is on this line, but for the sake of learning, I won't give the correct version, just a few hints:
newNode->link = back->link;
At the point where this code is being executed, which node does back point to? What does its link point to? Whose node's link do you need to modify?
As for finding this yourself, you could have used the debugger to figure out which line causes the crash; this would have indicated that something is wrong with a link value.
P.S. Your copy constructor doesn't actually copy the linked list; it just creates a new Queue object that points to the same linked list, so if you add an element to the copy, it will show up in the original Queue.
An access violation at address 0xCDCDCDCD means that your program loaded a pointer from uninitialized storage and then dereferenced it. Microsoft's debugging allocator uses this pattern for newly allocated uninitialized storage, and in a suitable compilation mode, also for stack locations. If you treat such uninitialized storage as a pointer variable, the pattern is recognizeable in that pointer. Moreover, it is almost certainly an invalid pointer that will trigger an exception. So the benefit is that the use of the invalid pointer is caught quickly, and the pattern tells you that the cause is quite likely uninitialized storage (though this is not 100% conclusive).
For example:
struct contains_pointer { char *str; } *ptr = malloc(sizeof *ptr);
strcpy(ptr->str, "abc"); // ptr->str is uninitialized
Or:
int *pint;
*pint = 0; // pint is uninitialized
To have the compiler and library overwrite uninitialized storage with a pattern like CDCDCD... can be quite helpful. You should pinpoint the location of the crash with the debugger, and then work backward from there: where did the pointer value originate and why wasn't it initialized.
(A bad pointer to the address CDCDCDCD could result in other ways: sheer fluke (unlikely) or a use-after-free bug: the program frees some memory but continues to keep a pointer to it, without using it for a while. The memory is then re-allocated to some other part of the program, and marked uninitialized, and by chance, the original user of the pointer makes a use of it, loading a pointer value from the memory. At that moment, a CDCDCDCD pointer results, so it looks like a use-before-init bug, when in fact it's a use-after-free bug. Debugging based on "memory poisoning" patterns is not accurate!)