Catching a memory leak?

closed account (4Gb4jE8b)
Does anyone have any tips on catching a memory leak in general? I know where the leak is coming from (approximately), but I've no idea how to fix it.

For what it's worth, I'm writing (for learning-the-language purposes) a stack, and hoping to grow it into a basic interpreter. I had gotten it to the point where it wasn't leaking earlier, however I (obviously) changed something that has recaused it to leak. I expect this to be in this to be in the add method of my LinkedList class, however concerning my previous issues were actually with my smart pointer and node class, I've included them as well.

I've included the parts I believe are to blame, however if they in fact aren't to blame, the full project can be located here: https://github.com/headlessgargoyle/Interpreter

main.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <iostream>
#include <string>
#include "smartLinkedList.h"
#include "stack.h"

using namespace std;

int main()
{
	for(int i = 0; i < 10000000; i++)
	{
		try
		{
			LinkedList<string> moo3;
			moo3.add("head");
			moo3.add("one");
			moo3.add("two");
			moo3.add("three");
			moo3.add("tail");
		}
		catch (exception &e)
		{
			cout << "Exception: " << e.what() << endl;
		}
		
		//garbage collect here
	}
	
	cout << "end" << endl;
	cin.ignore(1);
	return 0;
}


LinkedList (constructor, add):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#pragma once
#include "Node.h"
#include <string>
#include <sstream>
#include <stdexcept>

template <class type>
class LinkedList
{
private:
	int size;
	sPtr<node<type>> head; 

public:
	LinkedList(): head(NULL), size(0) {}

	bool add(type obj, int index = 0)
	{
		if(index > size)
			throw std::out_of_range("Index to be added at greater than size");

		sPtr<node<type>> temp(new node<type>(obj));

		if(index == 0)
		{
			temp->next = head;
			head = temp;
			size++;
			return true;
		}
		else
		{
			sPtr<node<type>> p = head;

			for(int i = 0; i<index-1; i++)
				p = p->next;
		
			temp->next = p->next;
			p->next = temp;

			size++;
			return true;
		}
	}
};


Node.h:
1
2
3
4
5
6
7
8
9
10
11
12
13
#pragma once
#include "smartPointer.h"

template <class type>
class node
{
public:
	type data;
	sPtr<node<type>> next;

	node(): next(NULL), data(NULL) {}
	node(type x): data(x), next(NULL) {}
};


smartPointer.h:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#pragma once

//for non-learning purposes, boost has a good smart pointer
template <class type>
class sPtr
{
private:
	type *p;
	int r; //referenceCount
	
	void add()
	{
		r++;
	}
	int release()
	{
		return --r;
	}

public:
	sPtr(): p(NULL), r(1) {}
	sPtr(type *pValue): p(pValue)
	{
		add();
	}
	sPtr(const sPtr<type> & sp): p(sp.p), r(sp.r)
	{
		add();
	}
	~sPtr()
	{
		if(release() == 0)
		{
			delete p;
		}
	}

	type* get()
	{
		return p;
	}

	type& operator*()
	{
		return *p;
	}
	type* operator->()
	{
		return p;
	}
	sPtr<type>& operator=(sPtr<type> sp)
	{
		std::swap(this->p, sp.p);
		std::swap(this->r, sp.r);
		add();

		return *this;
	}
};
Your sPtr class is incorrect. It makes value copies of the reference count, so it's possible for some pointers to be freed prematurely, and some others to be never freed.
closed account (4Gb4jE8b)
I figured it had something to do with the sPtr class (at least in part). That being said, I'm still not entirely sure how to actually solve the issue. I've tried a few different methods, and all of them continue to leak.

1
2
3
4
5
6
7
	sPtr<type>& operator=(const sPtr<type> &sp)
	{
		sPtr<type> temp(sp);
		std::swap(this->p, temp.p);
		std::swap(this->r, temp.r);
		return *this;
	}


I'm obviously missing something (likely basic, and probably due to the fact that I've been staring at this for hours). Mind posting some code of what it should look like?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
int *count;

sPtr(): p(NULL), r(new(1)) {}

sPtr<type>& operator=(const sPtr<type> &sp){
   release();
   value = sp.value;
   count = sp.count;
   add();
}

void release(){
   if( --*count == 0 ){
      delete value;
      delete count;
   }
}

void add(){
   ++*count;
}


I don't care enough, so don't take it `as is'


Edit: ¿why are you using a shared pointer for a linked list?
Edit: here you have other examples http://ootips.org/yonat/4dev/smart-pointers.html#WhyBugs
Last edited on
closed account (4Gb4jE8b)
@ne555, while I can't say I was able to get your code to work for me, I do appreciate the effort (even with a lack of care, which I can respect). That being said, I'll admit that I don't have the best understanding of the difference of the types of pointers (I did mention I was doing this for educational purposes, yes?). Honestly, reference counting seemed like a good idea for general purpose use, though I can see why it wouldn't need to be used for a linked last.

Though, for my use, wouldn't a shared pointer make it easier to reorganize the list and traverse it?
I fail to see how can it make it easier.

However, changing your list implementation would simplify the methods a lot
Implementing a list using a header node (that will not hold any value) and making it circular, makes that after an increment you always reach a node.
That simplifies some operations, as you don't need to check for invalid pointer, or threat the header in an special way
Topic archived. No new replies allowed.