I wrote a small queue class in C++, on Windows.
Just to test, I’m allocating 1,0000,000 ints and reading them back.
The queue is doing its job correctly and is very fast, but the problem is that after complete deallocation, there is some memory usage reported by the task manager. For example, I still get 2MB of memory although all those integers lead to 400MB+ of memory.
I thought it was due to the operating system not performing some sort of GC or whatever it is, but now I found that this value (2MB) becomes 13MB when I allocate 100,000,000 integers (10x the previous number). I cannot find the leak.
Here is the code; as you can see, I deallocate everything:
#pragma once
#include <exception>
template <class T>
class colist_item
{
public:
colist_item() { }
~colist_item() { }
T value;
colist_item *next;
};
template <class T>
class colist
{
public:
colist() { this->m_root = NULL; this->m_count = 0; }
~colist() { }
void enqueue(T value);
T dequeue();
T *peek();
int count();
private:
colist_item<T> *m_root;
int m_count;
};
template <class T>
void colist<T>::enqueue(T value)
{
if (this->m_root == NULL) {
this->m_root = new colist_item<T>();
this->m_root->value = value;
this->m_root->next = NULL;
} else {
colist_item<T> *tempitem = new colist_item<T>();
tempitem->value = value;
tempitem->next = this->m_root;
this->m_root = tempitem;
}
this->m_count++;
}
template <class T>
T colist<T>::dequeue()
{
if (this->m_root == NULL) {
throw std::exception();
} else {
T retval = this->m_root->value;
colist_item<T> *next = this->m_root->next;
delete this->m_root;
this->m_root = next;
this->m_count--;
return retval;
}
}
template <class T>
T *colist<T>::peek()
{
if (this->m_root == NULL) {
return NULL;
} else {
T retval = this->m_root->value;
return &retval;
}
}
template <class T>
int colist<T>::count()
{
return this->m_count;
}
Main:
#include <iostream>
#include <limits>
#include "colist.h"
#include <time.h>
const int kNumItems = 100000000;
using namespace std;
void puttest(colist<int> *list)
{
for(int i = 0; i < kNumItems; i++)
list->enqueue(i);
}
void readtest(colist<int> *list)
{
for(int i = 0; i < kNumItems; i++)
list->dequeue();
}
int main(int argc, char *argv[])
{
colist<int> list;
cout << "Testing with : " << kNumItems << " elements" << endl;
clock_t start = clock();
puttest(&list);
clock_t end = clock();
double ms = ((end - start));
cout << "puttest: " << ms << endl;
start = clock();
readtest(&list);
end = clock();
ms = ((end - start));
cout << "readtest: " << ms << endl;
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
OK a couple of bugs.
No destructor.
You are not leaking any memory because you remove all the items. But if you did not remove them all manually then your class would leak when it goes out of scope. Add a destructor that just deletes all the items on the list.
Dequeue is not exception safe:
Use the initializer list when constructing
You don’t need to use
thiseverywhere.I know it is encouraged in java but in C++ it is usually discouraged but recognized as a style thing. Personally I find its use cluttering.