I am trying to come up with a generic buffer (or heap container - not sure how to call it) for generic objects. So I could have a large number of them in contiguous memory.
The header I did works, but I was wondering if you guys could help me understand what am I doing wrong if anything, or any gotchas/bugs I am missing here. Or any other re-factoring I could do to make it better.
buffer.h
#ifndef _ENGINE_BUFFER
#define _ENGINE_BUFFER
#include <cstdlib>
#include <cstdio>
#include <typeinfo>
#include <cstring>
// Defining buffer struct:
template <typename T>
struct Buffer {
unsigned int _size;
unsigned int _number_of_objects;
unsigned int _head;
unsigned int _next;
unsigned int * _backlog;
int _backlog_head;
T* _buffer_address;
};
// Creating buffer:
template <typename T>
Buffer<T>* createBuffer(int size) {
Buffer<T>* _buffer = (Buffer<Sprite>*) calloc(1, sizeof(Buffer<T>));
if (_buffer) {
*(_buffer) = Buffer<T>();
_buffer->_size = size;
_buffer->_number_of_objects = 0;
_buffer->_head = 0;
_buffer->_next = 0;
_buffer->_backlog = (unsigned int*) calloc(size, sizeof(int));
_buffer->_backlog_head = -1;
_buffer->_buffer_address = (T*) calloc(size, sizeof(T));
if(_buffer->_buffer_address) {
return _buffer;
}
}
return (Buffer<T>*) nullptr;
}
// Adding object to buffer:
template <typename T>
int addObjectToBuffer(Buffer<T>* _buffer, const T &_obj) {
int _head = 0;
if (_buffer->_backlog_head > -1) {
_buffer->_buffer_address[_buffer->_backlog[_buffer->_backlog_head]] = _obj;
_head = _buffer->_backlog_head;
_buffer->_backlog_head--;
_buffer->_number_of_objects++;
} else {
if ( (int) (_buffer->_number_of_objects + 1) >= _buffer->_size){
T* _new_address = (T*) calloc((_buffer->_number_of_objects + 1) * 2, sizeof(T));
memcpy(_new_address, _buffer->_buffer_address, _buffer->_number_of_objects * sizeof(T));
free(_buffer->_buffer_address);
_buffer->_buffer_address = _new_address;
_buffer->_size = (_buffer->_number_of_objects + 1) * 2;
for (int i = _buffer->_head; i < _buffer->_size; i++){
_buffer->_buffer_address[i] = 0;
}
}
_buffer->_buffer_address[_buffer->_head] = _obj;
_buffer->_number_of_objects++;
_head = _buffer->_head;
_buffer->_head++;
}
return _head;
}
// Getting number of objects in buffer:
template <typename T>
unsigned int bufferGetSize(Buffer<T>* _buffer) {
return (int) _buffer->_number_of_objects;
}
// Getting next object in buffer:
template <typename T>
T* bufferGetNext(Buffer<T>* _buffer) {
if (_buffer->_backlog_head > -1){
for (int i = 0; i <= _buffer->_backlog_head; i++ ) {
if (_buffer->_backlog[i] == _buffer->_next) _buffer->_next++;;
}
}
unsigned int _next = _buffer->_next;
if (_next < _buffer->_head) {
_buffer->_next++;
return &_buffer->_buffer_address[_next];
} else {
_buffer->_next = 0;
bufferGetNext(_buffer);
}
}
// Reset iterator head:
template <typename T>
void bufferResetHead(Buffer<T>* _buffer){
_buffer->_next = 0;
}
// Deleting object from buffer:
template <typename T>
void deleteObjectFromBuffer(Buffer<T>* _buffer, unsigned int _obj_index) {
if (_obj_index >= 0 && _obj_index <= _buffer->_head) {
bool _obj_exists = false;
for (int i = _buffer->_backlog_head; i >= 0; i-- ) {
if (_buffer->_backlog[i] == _obj_index){
_obj_exists = true;
fprintf(stderr, "\n[ Warning: object_deleted_twice | buffer: %#010x | object: %#010x | index: \"%d\" ]\n",
_buffer, &_buffer->_buffer_address[_obj_index], _obj_index);
}
}
if (!_obj_exists) {
_buffer->_backlog_head++;
_buffer->_backlog[_buffer->_backlog_head] = _obj_index;
_buffer->_number_of_objects--;
}
} else {
fprintf(stderr, "\n[ Warning: index_out_of_range | buffer: %#010x | index: \"%d\" ]\n",
_buffer, _obj_index);
}
}
// Deleting buffer:
template <typename T>
void deleteBuffer(Buffer<T>* _buffer) {
free(_buffer->_buffer_address);
free(_buffer);
}
// Print buffer memory:
template <typename T>
void printBufferMemory(Buffer<T>* _buffer, unsigned int _number_of_columns, bool _print_address) {
int _column_count = 0;
printf("\n");
printf("[ Number of objects in buffer: %#02d | Actual buffer size: %#02d ]\n", _buffer->_number_of_objects, _buffer->_size);
for (int i = 1; i < 11 * _number_of_columns; i++) {
printf("=");
}
printf("\n");
for (int i = 0; i < _buffer->_size; i++) {
if (_column_count > _number_of_columns - 1) {
printf("\n");
_column_count = 0;
}
if (_print_address) {
printf("%#010x ", &_buffer->_buffer_address[i]);
} else {
printf("%#010d ", *(&_buffer->_buffer_address[i]));
}
_column_count++;
}
printf("\n");
for (int i = 1; i < 11 * _number_of_columns; i++) {
printf("=");
}
printf("\n");
}
#endif // _ENGINE_BUFFER
sprite.h
#ifndef _SPRITE
#define _SPRITE
struct Sprite {
int value = 0;
Sprite(int n){
value = n;
}
};
#endif // _SPRITE
main.cpp
#include <cstdio>
#include <cstdlib>
#include "sprite.h"
#include "buffer.h"
using namespace std;
int main()
{
int buffer_size = 512;
int object_number = 512;
Buffer<Sprite>* engine_buffer = createBuffer<Sprite>(buffer_size);
for (int i = 0; i < object_number; i++) {
addObjectToBuffer(engine_buffer, Sprite(i + 100));
}
for (int i = 0; i < bufferGetSize(engine_buffer); i++) {
printf("Value of Sprite %d is: %d\n", i + 1, bufferGetNext(engine_buffer)->value);
}
printBufferMemory(engine_buffer, 10, false);
deleteBuffer(engine_buffer);
return(0);
}
Related
I find myself in a difficult situation. I have a program which is supposed to delete any memory that is dynamically allocated, but whenever I try to call the relevant methods, it comes up with a memory heap corruption.
It seems to work when I don't call the methods, but then I've probably caused a ton of memory leaks. Would anyone have any idea what is going on?
The code is below:
CSVFile.h:
#pragma once
class InputPattern;
class OutputPattern;
class CSVFile
{
private:
const int NAME_MAX = 100;
char* name;
char** buffer;
bool loadedFlag;
int patternCount;
InputPattern** inputs;
OutputPattern** outputs;
void setLoadedFlagTrue();
void setLoadedFlagFalse();
public:
CSVFile();
~CSVFile();
CSVFile(const char*);
void setName(const char*);
char* getFilename(char*, int);
bool getLoadedFlag();
int loadFile();
InputPattern* getInputPattern(int);
OutputPattern* getOutputPattern(int);
void addInputPattern(InputPattern*);
void addOutputPattern(OutputPattern*);
void deleteInputPattern();
void deleteOutputPattern();
void printMetaData();
void printPatterns();
void deleteBuffer();
};
CSVFile.cpp:
#include "CSVFile.h"
#include "InputPattern.h"
#include "OutputPattern.h"
#include <stdio.h>
#include <string.h>
void CSVFile::setLoadedFlagTrue()
{
loadedFlag = true;
}
void CSVFile::setLoadedFlagFalse()
{
loadedFlag = false;
}
CSVFile::CSVFile()
{
name = NULL;
buffer = NULL;
inputs = NULL;
outputs = NULL;
patternCount = 0;
inputs = new InputPattern*[10];
outputs = new OutputPattern*[10];
buffer = new char*[4];
int i;
for (i = 0; i < 10; i++)
{
inputs[i] = new InputPattern();
outputs[i] = new OutputPattern();
buffer[i] = new char[NAME_MAX];
}
}
CSVFile::~CSVFile()
{
delete name;
name = NULL;
}
CSVFile::CSVFile(const char * filename)
{
name = NULL;
buffer = NULL;
inputs = NULL;
outputs = NULL;
patternCount = 0;
inputs = new InputPattern*[10];
outputs = new OutputPattern*[10];
int i;
for (i = 0; i < 10; i++)
{
inputs[i] = new InputPattern();
outputs[i] = new OutputPattern();
}
name = new char[NAME_MAX];
strcpy(name, filename);
}
void CSVFile::setName(const char * filename)
{
name = new char[NAME_MAX];
strcpy(name, filename);
}
char* CSVFile::getFilename(char * outBuff, int outBuffSize)
{
outBuff = new char[outBuffSize + 1];
strncpy(outBuff, name, outBuffSize);
return outBuff;
}
bool CSVFile::getLoadedFlag()
{
if (name == NULL)
{
setLoadedFlagFalse();
return loadedFlag;
}
if (patternCount == 10)
setLoadedFlagTrue();
else
setLoadedFlagFalse();
return loadedFlag;
}
int CSVFile::loadFile()
{
FILE* f;
if ((f = fopen(name, "r")) == NULL)
{
printf("File failed to open\n");
return 0;
}
for (patternCount = 0; patternCount < 4; patternCount++)
{
fgets(buffer[patternCount], 100, f);
}
patternCount = 0;
/*ask about input interaction; potentially remove these variables afterwards*/
float tIn, rIn, gIn, bIn, tOut, oOut;
/*might change this to make it more flexible*/
while (patternCount < 10)
{
fscanf(f, "%f,%f,%f,%f,%f,%f", &tIn, &rIn, &gIn, &bIn, &tOut, &oOut);
printf("%f,%f,%f,%f,%f,%f\n", tIn, rIn, gIn, bIn, tOut, oOut);
inputs[patternCount]->setT(tIn);
inputs[patternCount]->setR(rIn);
inputs[patternCount]->setG(gIn);
inputs[patternCount]->setB(bIn);
outputs[patternCount]->setT(tOut);
outputs[patternCount]->setO(oOut);
patternCount++;
}
fclose(f);
return patternCount;
}
InputPattern * CSVFile::getInputPattern(int index)
{
if (index >= 0 && index < 10)
return inputs[index];
else
return 0;
}
OutputPattern * CSVFile::getOutputPattern(int index)
{
if (index >= 0 && index < 10)
return outputs[index];
else
return 0;
}
void CSVFile::addInputPattern(InputPattern * in)
{
inputs[patternCount] = in;
patternCount++;
}
void CSVFile::addOutputPattern(OutputPattern * out)
{
outputs[patternCount] = out;
patternCount++;
}
void CSVFile::deleteInputPattern()
{
int i;
for (i = 0; i < patternCount; i++)
{
delete inputs[i];
}
delete inputs;
inputs = NULL;
}
void CSVFile::deleteOutputPattern()
{
int i;
for (i = 0; i < patternCount; i++)
{
delete outputs[i];
}
delete outputs;
outputs = NULL;
}
void CSVFile::printMetaData()
{
int i;
for (i = 0; i < 4; i++)
{
printf("%s", buffer[i]);
}
}
void CSVFile::printPatterns()
{
/*to be completed*/
int i;
for (i = 0; i < patternCount; i++)
{
printf("Class number %d\n", i + 1);
printf("T in = %f\n", inputs[i]->getT());
printf("R in = %f\n", inputs[i]->getR());
printf("G in = %f\n", inputs[i]->getG());
printf("B in = %f\n", inputs[i]->getB());
printf("T out = %f\n", outputs[i]->getT());
printf("O out = %f\n", outputs[i]->getO());
}
}
void CSVFile::deleteBuffer()
{
int i;
for (i = 0; i < patternCount; i++)
{
delete buffer[i];
}
delete buffer;
buffer = NULL;
}
TestHarness.cpp sample (this is executed in the main function)
bool TestHarness::testCSVFileSetFilepath() /*this works fine*/
{
bool testResult = false;
CSVFile* test = NULL;
test = new CSVFile();
char *testName = NULL;
test->setName("test.txt");
testName = test->getFilename(testName, 10);
if (strcmp("test.txt", testName) == 0)
testResult = true;
delete test;
delete testName;
test = NULL;
testName = NULL;
return testResult;
}
...........................
bool TestHarness::testCSVFileLoadFile() /*this causes the corruption*/
{
bool testResult = false;
CSVFile* test = NULL;
test = new CSVFile();
test->setName("C:/Users/user/Documents/AssignmentsSem2/ExampleFile.csv");
if (test->loadFile() == 10)
testResult = true;
test->deleteInputPattern();
test->deleteOutputPattern();
test->deleteBuffer(); /*these three above methods are the ones I'm talking about*/
delete test;
test = NULL;
return testResult;
}
You can check for memory leaks with
#define _CRTDBG_MAP_ALLOC
#include<crtdbg.h>
struct AtExit
{
~AtExit()
{
_CrtDumpMemoryLeaks();
}
}doAtExit;
just outside the main method.
This runs whenever your program ends. All it really does is display whether you have a memory leak or not. Doesn't help with actually finding them.
You might need Visual Studio for this.
This is how it looks when a memory leak is found
this my Library.h file, before the Library used to do All the dirty work: in term of manipulating the arrays and stuff, but now I am trying to make the Library the middle man that just invoke the call that has to do with any array manipulations. My problem is I am trying to have one instance of Patron array, that would hold all the patrons in the Library.
#ifndef LIBRARY_H
#define LIBRARY_H
#include <string>
#include "types.h"
#include "Book.h"
#include "Patron.h"
#include "PatronArray.h"
//class PatronArray
class Library
{
public:
Library();
~Library();
void init();
int addBook(Book*);
int addPatron(Patron*);
int remPatron(int);
int findBook(int, Book**, int*);
int findPatron(string, string, Patron**, int*);
int getMaxCollIndex();
int getMaxPatronsIndex();
Book* getBook(int);
Patron* getPatron(int);
private:
Book* collection[MAX_COLL_SIZE];
PatronArray* patrons;
int maxCollIndex;
int maxPatronsIndex;
};
#endif
This is my Library.cc file
#include "Library.h"
Library::Library()
: maxCollIndex(0)
{
patrons = new PatronArray;
for (int i=0; i<MAX_COLL_SIZE; ++i) {
collection[i] = 0;
}
}
Library::~Library()
{
delete patrons;
for (int i=0; i<maxCollIndex; ++i)
delete collection[i];
}
int Library::getMaxCollIndex() { return maxCollIndex; }
int Library::getMaxPatronsIndex()
{
return patrons->getMaxPatronsIndex();
}
Book* Library::getBook(int index)
{
if (index < 0 || index >= maxCollIndex)
return 0;
return collection[index];
}
Patron* Library::getPatron(int index)
{
return patrons->getPatron(index);
}
void Library::init()
{
Book* newBook;
Patron* newPatron;
newBook = new Book("Ender's Game", "Orson Scott Card", 1985);
addBook(newBook);
newBook = new Book("Dune", "Frank Herbert", 1965);
newBook->setStatus(LOST);
addBook(newBook);
newBook = new Book("Foundation", "Isaac Asimov", 1951);
addBook(newBook);
newBook = new Book("Hitch Hiker's Guide to the Galaxy", "Douglas Adams", 1979);
addBook(newBook);
newPatron = new Patron("Jack", "Shephard");
addPatron(newPatron);
}
int Library::addBook(Book* book)
{
if (maxCollIndex >= MAX_COLL_SIZE - 1) {
return C_NOK;
}
collection[maxCollIndex++] = book;
return C_OK;
}
int Library::addPatron(Patron* patron)
{
// the lbrary is the middle ma that invokesthe calls
//return patronArray->addPatron(patron);
return patrons->addPatron(patron);
}
int Library::remPatron(int index)
{
return patrons->remPatron(index);
}
int Library::findPatron(string fn, string ln, Patron** patron, int* index)
{
return patrons->findPatron(fn,ln,patron,index);
}
int Library::findBook(int id, Book** book, int* index)
{
for (int i=0; i<maxCollIndex; ++i) {
if (collection[i] == 0)
continue;
if (collection[i]->getId() == id) {
*book = collection[i];
*index = i;
return C_OK;
}
}
*book = 0;
*index = -1;
return C_NOK;
}
This is my PatronArray.h that holds all the Patrons registered within the Library.
#ifndef PATRONARRAY_H
#define PATRONARRAY_H
#include "Patron.h"
#include "Book.h"
#include "types.h"
//class Patron;
class PatronArray
{
public:
PatronArray();
~PatronArray();
int addPatron(Patron*);
int remPatron(int);
int findPatron(string, string, Patron**, int*);
int getMaxPatronsIndex();
Patron* getPatron(int);
private:
Patron* patrons[MAX_COLL_SIZE];
int maxPatronsIndex;
};
#endif
and this is the PatronArray.cc file and please, I know there is better way of doing this by doing templating which I currently dont understand yet plus this way helps me understand the whole object oriented style.
#include<iostream>
#include<string>
#include "PatronArray.h"
/*
* Default constructor: recheck this later
*/
PatronArray::PatronArray()
:maxPatronsIndex(0)
{
for (int i = 0; i < MAX_COLL_SIZE; ++i) {
patrons[i] = 0;
}
}
/*
* Destructor: recheck this later
*/
PatronArray::~PatronArray()
{
for (int i = 0; i < maxPatronsIndex; ++i)
delete patrons[i];
}
//get the maxindex
int PatronArray::getMaxPatronsIndex() { return maxPatronsIndex; }
/*
* Adds the given Patron to the given patrons Array
*/
int PatronArray::addPatron(Patron* patron)
{
if (maxPatronsIndex >= MAX_COLL_SIZE - 1) {
return C_NOK;
}
patrons[maxPatronsIndex++] = patron;
return C_OK;
}
/*
* Used for removing a patron in the patrons array
*/
int PatronArray::remPatron(int index)
{
if (index < 0 || index >= maxPatronsIndex)
return C_NOK;
delete patrons[index];
patrons[index] = 0;
return C_OK;
}
/*
* Searches for the patron; if found, sets the contents of the second
* parameter to that patron pointer, sets the contents of the third parameter to
* its index in the collection, and returns C_OK; if not found, sets the
* contents of the second parameter to zero, the theird to -1, and returns C_NOK
*/
int PatronArray::findPatron( string fn, string ln, Patron** patron, int* index)
{
for (int i = 0; i < maxPatronsIndex; ++i) {
if (patrons[i] == 0)
continue;
if (patrons[i]->getFname() == fn && patrons[i]->getLname() == ln) {
*patron = patrons[i];
*index = i;
return C_OK;
}
}
*patron = 0;
*index = -1;
return C_NOK;
}
Patron* PatronArray::getPatron(int index)
{
if (index < 0 || index >= maxPatronsIndex)
return 0;
return patrons[index];
}
I forgot to link my PatronArray.cc to Library.cc in my makefile, thank you Jack!
I have created my vector class template and I have already done my employee classes of hourly and I salaried. I want to use the vector of employee pointers instead of the array of employee pointers, I'm trying to do that but when I run it just breaks while I have no error listed.
Also, I have used the at function like( payroll.at(i)->writeFile(out); ) to get access to an element, but I don't know what's wrong.
Any suggestion?
Thanks
here is my code:
myvector class template:
#include <iostream>
#include <string>
#include <cassert>
#include <algorithm>
const int CAPACITY = 4;
template <class T>
class MyVector {
public:
MyVector();
MyVector( int size);
MyVector( int size, const T & initial);
MyVector(const MyVector<T> & v);
~MyVector();
int capacity() const;
int size() const;
void push_back(const T & value);
//T & operator[](unsigned int index);
MyVector<T> & operator=(const MyVector<T> &);
void clear();
T at(int i);
friend ostream& operator<<(ostream &out, const MyVector<T>& );
private:
int applied;
int my_size;
int my_capacity;
T * buffer;
T * daArray;
};
template<class T>
MyVector<T>::MyVector()
{
my_capacity = 0;
my_size = 0;
buffer = 0;
applied = 0;
}
template<class T>
MyVector<T>::MyVector(const MyVector<T> & v)
{
my_size = v.my_size;
my_capacity = v.my_capacity;
buffer = new T[my_size];
for ( int i = 0; i < my_size; i++)
buffer[i] = v.buffer[i];
}
template<class T>
MyVector<T>::MyVector(int size)
{
my_capacity = size;
my_size = size;
buffer = new T[size];
}
template<class T>
MyVector<T>::MyVector( int size, const T & initial)
{
my_size = size;
my_capacity = size;
buffer = new T [size];
for (unsigned int i = 0; i < size; i++)
buffer[i] = initial;
//T();
}
template<class T>
MyVector<T> & MyVector<T>::operator = (const MyVector<T> & v)
{
delete[ ] buffer;
my_size = v.my_size;
my_capacity = v.my_capacity;
buffer = new T [my_size];
for (int i = 0; i < my_size; i++)
buffer[i] = v.buffer[i];
return *this;
}
template<class T>
void MyVector<T>::push_back(const T & i)
{
if (my_capacity == 0)
{
my_capacity = 1;
my_size = 1;
applied= 0;
buffer = new T[1];
buffer[0] = i;
}
else
{
if (applied+1 == my_capacity)
{
int newCapacity = my_capacity * CAPACITY;
daArray = new T[newCapacity];
for (int i = 0; i < my_size; i++)
{
daArray[i] = buffer[i];
}
my_capacity = newCapacity;
delete buffer;
my_size++;
applied++;
buffer[applied] = i;
}
else
{
if (my_size == applied + 1)
my_size++;
applied++;
buffer[applied] = i;
}
}
}
template<class T>
int MyVector<T>::size()const//
{
return my_size;
}
template<class T>
int MyVector<T>::capacity()const
{
return my_capacity;
}
template<class T>
MyVector<T>::~MyVector()
{
delete[ ] buffer;
}
template <class T>
void MyVector<T>::clear()
{
my_capacity = 0;
my_size = 0;
buffer = 0;
}
template <class T>
T MyVector<T>::at(int i)
{
if (i < 0 || i > my_size -1)
{
string error = "Index is undefined";
throw error;
}
return buffer[i];
}
template <class T>
ostream& operator<<(ostream &out, const MyVector<T>& v)
{
for (unsigned i = 0; i < v.size(); i++)
{
out << v[i] << " ";
}
return out;
}
main
int main() {
MyVector< employee*> payroll;
payroll.push_back(new Hourly ("H. Potter", "Privet Drive", "201-9090", 40, 12.00));
payroll.push_back(new Salaried ( "A. Dumbledore", "Hogewarts", "803-1230", 1200));
ofstream out;
out.open(file);
if (out.fail()) {
cout<<" could not open the file"<<endl;
system("PAUSE");
}
for (int i = 0; i < SIZE; i++) {
payroll.at(i)->writeFile(out);
}
out.close( );
}
You have a bug in your push_back method. You need something like this
if (applied+1 == my_capacity)
{
int newCapacity = my_capacity * CAPACITY;
daArray = new T[newCapacity];
for (int i = 0; i < my_size; i++)
{
daArray[i] = buffer[i];
}
my_capacity = newCapacity;
delete buffer;
buffer = daArray; // new line here
my_size++;
applied++;
buffer[applied] = i;
}
See where I've put the comment // new line here
As an exercise (largely an exercise in trying to write something using pointers), I'm writing a cache simulation, specifically of the pseudo least recently used system from the old 486. I'm getting an "Access violation reading location" error on the line:
int min = treeArray[set]->root->findPLRU();
Initially the treeArray seems to be initialised properly (if I pause the program at the start and take a look, it's all as should be), but when the programme breaks and I delve in to examine things the root of the tree in question isn't defined.
I feel it's quite probable that I'm making some sort of very elementary pointer mistake, which is causing the pointer to the node to be "lost" somewhere, but I've no clue what it might be. Is there something in particular I need to do to "hold on" to a pointer value?
#include "stdafx.h"
#include "stdlib.h"
#include <conio.h>
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <io.h>
#include "main.h"
//char fn[80]; // trace filename
int tf; // trace file
trace buf[BUFSZ / sizeof(trace)]; // buffer SIZE
int LRUHits = 0;
int pLRUHits = 0;
int randomHits = 0;
int height;
int cachelinenumber;
//log2 helper function
int log2(int n)
{
int i = 0;
while (n)
{
n = n >> 1;
i++;
}
return i - 1;
}
class CacheLine{
public:
int tag;
int access;
CacheLine();
};
class Cache;
class Node{
public:
bool goRight;
Node* left;
Node* right;
int leftCacheLine;
int rightCacheLine;
Node(int depth) // constructor
{
goRight = false;
if (depth < height - 1)
{
left = new Node(depth + 1);
right = new Node(depth + 1);
leftCacheLine = -1;
rightCacheLine = -1;
}
else
{
leftCacheLine = cachelinenumber;
cachelinenumber++;
rightCacheLine = cachelinenumber;
cachelinenumber++;
}
//printf("Depth: %d, Height: %d, Left: %d, Right: %d\n", depth, height, leftCacheLine, rightCacheLine);
}
~Node()
{
delete left;
delete right;
}
int findPLRU()
{
if (leftCacheLine < 0 || rightCacheLine < 0)
{
if (goRight)
{
goRight = false;
return right->findPLRU();
}
else
{
goRight = true;
return left->findPLRU();
}
}
else
{
if (goRight)
{
goRight = false;
return rightCacheLine;
}
else
{
goRight = true;
return leftCacheLine;
}
}
}
};
class Tree{
public:
Node* root;
Tree()
{
root = new Node(0);
}
~Tree()
{
delete root;
}
};
//cache class
class Cache
{
public:
CacheLine *cache;
int l, k, n, replacementPolicy;
int log2l, log2n;
int access;
Tree** treeArray;
//constructor
Cache(int ll, int kk, int nn, int _replacementPolicy)
{
l = ll;
k = kk;
n = nn;
replacementPolicy = _replacementPolicy;
log2l = log2(l);
log2n = log2(n);
cache = (CacheLine*)malloc(sizeof(CacheLine)*k*n);
for (int i = 0; i < k*n; i++)
{
cache[i].tag = 0x80000000;
cache[i].access = 0;
}
if (replacementPolicy == 1)
{
cachelinenumber = 0;
treeArray = new Tree*[n];
for (int i = 0; i < n; i++)
{
treeArray[i] = new Tree();
}
}
access = -1;
}
//destructor
~Cache()
{
free(cache);
}
//test for hit
void hit(int a)
{
access++;
int set = (a >> log2l) & (n - 1);
int tag = a >> (log2n + log2l);
CacheLine* c = &cache[set*k];
for (int i = 0; i < k; i++)
{
if (c[i].tag == tag)
{
c[i].access = access;
if (replacementPolicy == 0)
LRUHits++;
else if (replacementPolicy == 1)
pLRUHits++;
else if (replacementPolicy == 2)
randomHits++;
break;
}
}
if (replacementPolicy == 0) //LRU
{
int min = 0;
int minv = c[0].access;
for (int i = 1; i < k; i++)
{
if (c[i].access < minv)
{
minv = c[i].access;
min = i;
}
}
c[min].tag = tag;
c[min].access = access;
}
else if(replacementPolicy == 1) // pseudoLRU
{
int min = treeArray[set]->root->findPLRU();
c[min].tag = tag;
c[min].access = access;
}
else // random
{
srand(clock());
int randomNumber = rand()%k;
c[randomNumber].tag = tag;
c[randomNumber].access = access;
}
return;
}
};
void analyse (int l, int k, int n)
{
height = log2(k) + 1;
char fn[] = "ico0.trace";
if ((tf = open(fn, _O_RDONLY | _O_BINARY )) == -1) {
printf("unable to open file %s\n", fn);
exit(0);
}
LRUHits = 0;
pLRUHits = 0;
randomHits = 0;
Cache *cache0 = new Cache(l, k, n, 0); // LRU
Cache *cache1 = new Cache(l, k, n, 1); // pseudoLRU
Cache *cache2 = new Cache(l, k, n, 2); // random
int bytes, word0, a, type, burstcount;
int hits = 0;
int tcount = 0;
while (bytes = read(tf, buf, sizeof(buf)))
{
for (int i = 0; i < bytes / (int) sizeof(trace); i++, tcount++)
{
word0 = buf[i].word0;
a = (word0 & ADDRESSMASK) << 2;
type = (word0 >> TYPESHIFT) & TYPEMASK;
burstcount = ((word0 >> BURSTSHIFT) & BURSTMASK) + 1;
cache0->hit(a);
cache1->hit(a);
cache2->hit(a);
}
}
printf("Hits: %d Total: %d\n", LRUHits, tcount);
printf("Hits: %d Total: %d\n", pLRUHits, tcount);
printf("Hits: %d Total: %d\n\n\n", randomHits, tcount);
delete cache0;
delete cache1;
delete cache2;
}
int _tmain(int argc, _TCHAR* argv[])
{
//analyse(16, 1, 8);
analyse(16, 2, 512);
//analyse(16, 4, 256);
//analyse(16, 8, 128);
//analyse(16, 1024, 1);
_getch();
return 0;
}
Your question hasn't yet been pounced upon, probably because your code still doesn't compile since you've not provided main.h.
And even then it would annoy most folks trying to help you because you make no mention of the ico0.trace file that is required to prevent the code from immediately exiting.
You say int min = treeArray[set]->root->findPLRU(); access violates.
1) the value of set can never exceed the size n of your treeArray since you & n-1 the range of input values.
2) since your ~Tree() destructor is never called there will always be a treeArray[set]->root
3) since you *always create new left & right nodes whenever leftCacheLine = -1 or rightCacheLine = -1 it cannot be due to recursive findPLRUs
So, the pointer to the node is not being "lost" somewhere; it is being stomped on.
Try replacing:
int min = treeArray[set]->root->findPLRU();
c[min].tag = tag;
c[min].access = access;
with:
int min = treeArray[set]->root->findPLRU();
if (min >= k*n)
{
printf("ook\n");
}
else
{
c[min].tag = tag;
c[min].access = access;
}
and I think you will discover what's doing the stomping. ;)
I have problem in implementing a disjoint set ADT in C++ due to the fact that our teacher only explained the union and find operations. I fully understand the concepts of union and find but I am still confused about how to implement them.
Could someone please give me an idea of the implementation and also explain what the interface of this data structure should look like?
You have way too many requirements, we're not here to do your homework for you.
Have a look at http://en.wikipedia.org/wiki/Disjoint-set_data_structure
#include <iostream>
template<typename T>
class Disjoint_sets
{
public:
int FIND(int pos);
bool in_same_set(T data_element_1, T data_element_2);
void UNION_IF_EQUIVALENT(T data_element_1, T data_element_2);
void UNION(T data_element_1, T data_element_2);
Disjoint_sets(bool (*is_equivalent)(T, T));
Disjoint_sets();
Disjoint_sets(T* data_arr, bool (*is_equivalent)(T, T),int size);
void insert(T data_element);
bool is_root(int pos_number);
int get_pos(T data_element);
void partition();
void print_partition();
private:
T* data;
int* parent_pos;
int* number_of_children;
int size;
bool (*isequivalent)(T D1, T D2);
};
template<typename T>
Disjoint_sets<T>::Disjoint_sets()
{
data = NULL;
parent_pos = NULL;
number_of_children = NULL;
size = 0;
isequivalent = NULL;
}
template<typename T>
Disjoint_sets<T>::Disjoint_sets(bool (*is_equivalent)(T, T))
{
isequivalent = is_equivalent;
data = NULL;
parent_pos = NULL;
number_of_children = NULL;
size = 0;
}
template<typename T>
Disjoint_sets<T>::Disjoint_sets(T* data_arr, bool (*is_equivalent)(T, T), int size)
{
data = new T[size];
parent_pos = new int[size];
number_of_children = new int[size];
this->size = size;
isequivalent = is_equivalent;
for (int i = 0; i < size; i++)
{
data[i] = data_arr[i];
parent_pos[i] = -1;
number_of_children[i] = 0;
}
}
template<typename T>
bool Disjoint_sets<T>::is_root(int pos)
{
if (pos<0 && pos>size - 1)
{
std::cout << "Error, invalid pos supplied to is_root\n";
return false;
}
if (parent_pos[pos] == -1)
{
return true;
}
else
{
return false;
}
}
template <typename T>
int Disjoint_sets<T>::FIND(int pos)
{
while (!is_root(pos))
{
pos = parent_pos[pos];
}
return pos;
}
template<typename T>
bool Disjoint_sets<T>::in_same_set(T data_element_1, T data_element_2)
{
return FIND(get_pos(data_element_1)) == FIND(get_pos(data_element_2));
}
template<typename T>
int Disjoint_sets<T>::get_pos(T data_element)
{
for (int i = 0; i < size; i++)
{
if (data[i] == data_element)
{
return i;
}
}
std::cout << "Could not find element\n";
return -1;
}
template <typename T>
void Disjoint_sets<T>::UNION(T data_element_1, T data_element_2)
{
int data_parent_1_pos = FIND(get_pos(data_element_1));
int data_parent_2_pos = FIND(get_pos(data_element_2));
if ( data_parent_1_pos==data_parent_2_pos )
{
return;
}
if (number_of_children[data_parent_1_pos] >= number_of_children[data_parent_2_pos])
{
parent_pos[data_parent_2_pos] = data_parent_1_pos;
}
else
{
parent_pos[data_parent_1_pos] = data_parent_2_pos;
}
}
template <typename T>
void Disjoint_sets<T>::UNION_IF_EQUIVALENT(T data_element_1, T data_element_2)
{
if (FIND(get_pos(data_element_1)) == FIND(get_pos(data_element_2)))
{
return;
}
if (isequivalent(data_element_1, data_element_2))
{
UNION(data_element_1, data_element_2);
}
}
template<typename T>
void Disjoint_sets<T>::partition()
{
for (int i = 0; i < size; i++)
{
for (int j = i + 1; j < size; j++)
{
UNION_IF_EQUIVALENT(data[i], data[j]);
}
}
}
template <typename T>
void Disjoint_sets<T>::print_partition()
{
for (int i = 0; i < size; i++)
{
if (is_root(i))
{
for (int j = 0; j < size; j++)
{
if (FIND(j) == i)
{
std::cout << data[j] << " ";
}
}
}
std::cout << "\n";
}
}
template <typename T>
bool lol(int a, int b)
{
return a * a == b * b;
}
int main()
{
int arr[6] = { -1,1,2,3,-3,4 };
Disjoint_sets<int> d(arr,lol<int>, 6);
d.partition();
d.print_partition();
}