C++ pointer "losing" its value - c++

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. ;)

Related

Pointer to array of pointers to structs in C++

I need some help, I'm learing data structers and I got a task to write a programm based on array of pointers to structres which can add elements and do other task with array.I have next model of levels:
first level --> net of shops
second level --> shop
third level --> goods
I've written types for this
typedef struct
{
QString date;
QString prod_code;
QString name;
}goods;
typedef struct
{
QString address;
QString number;
void **sublevel;
}shop;
typedef struct
{
QString website;
QString name;
QString owner;
QString address;
void **sublevel;
}net;
Then I've created global variable void **Start which points to array of pointers:
// init list
void ** init_list()
{
void** p = new void*[SIZE_AR];
p = p+2;
((int*)p)[COUNT_POS] = 0;
((int*)p)[SIZE_POS] = SIZE_AR;
return p;
}
void ** Start = init_list();
COUNT_POS - index of elements where I store count of currently used elemnets
SIZE_POS - size of array allocated in dynamic memory
SIZE_AR - default size for array
But I get segmentation fault when I try to add to element to the last level
(for previous two ones works fine):
// expand array if it overfilled
void ExpandArrPtr (void **&ar, int &SizeAr, int Cnt)
{
void **arW;
arW = new void*[SizeAr+DELTA+2];
for (int K = SizeAr-1; K >= 0; K--) {
arW[K+2] = ar[K];
}
SizeAr = SizeAr + DELTA;
ar=ar-2;
delete []ar;
ar=arW+2;
((int*)ar)[COUNT_POS] = Cnt;
((int*)ar)[SIZE_POS] = SizeAr;
}
// binary search
void bin_search(void **start, QString key, int &pos, bool &find, Cmpmethod func)
{
int mid;
int high, low;
find = false;
if((int*)start[COUNT_POS] == 0)
{
pos = 0;
qDebug()<<"zero elem\n";
return;
}
low = 0;
high = ((int*)start)[COUNT_POS] - 1;
do
{
mid = (high + low) / 2;
int result = func(start[mid], key);
if(result == 0)
{
pos = mid;
find = true;
return;
}
else if(result == 1)
{
high = mid - 1;
}
else
{
low = mid + 1;
}
}while(low <= high);
pos = low;
}
// function for adding in any level
void addtosort(void **&start, void *pnew, int pos)
{
int count = ((int*)start)[COUNT_POS];
int size = ((int*)start)[SIZE_POS];
if(count == size)
{
ExpandArrPtr(start, size, count);
}
if(pos == count)
{
start[pos] = pnew;
}
else
{
for(int i = count;i >= pos;i--)
{
start[i+1] = start[i];
}
start[pos] = pnew;
}
count++;
((int*)start)[COUNT_POS] = count;
}
void add_goods(void **&Start, goods * Pnew)
{
int pos;
bool find;
bin_search((((shop*)(Start))->sublevel), Pnew->name, pos, find, compare_goods);
addtosort((((shop*)(Start))->sublevel), Pnew, pos);
}
// finding the item in second level to add
void find_place(QString key)
{
int pos;
bool find;
int count = ((int*)Start)[COUNT_POS];
for(int i = 0;i < count;i++)
{
bin_search(((net*)(Start)[i])->sublevel, key, pos, find, compare_shop);
if(find)
{
goods * Pnew = new goods;
Pnew->date = "foo"
Pnew->name = "bar"
add_goods(((net*)(Start)[pos])->sublevel, Pnew);
break;
}
}
}
What can cause such problem?

Discrete Event Simulation Algorithm debug

I am working on a discrete event simulation program in C++. My output is completely incorrect but all the output values are pretty close to the correct output. I have tried debugging my algorithm but I couldn't find any errors. Below is my main algorithm for the simulation.
I implemented the event priority queue using a min heap and array. I am not allowed to use any STL libraries. The FIFO queue used in the code is a linked list. When I print the event time at the top of the priority queue, the events are not always getting passed in ascending order (which I think is how event priority queues are supposed to work) and I do not understand why. The ascending order is breached mostly around event completion times. Please help!
#include <iostream>
#include <fstream>
#include "PQueue.h"
#include "SPqueue.h"
#include "LinkedList.h"
using namespace std;
int serverCount; //number of servers
Spqueue spq; //priority queue for servers
Pqueue pq; //priority queue for events
LinkedList list; //FIFO queue to put arriving events in
double totalTime; //variables for statistics calculation
double timeNow;
double totalWait;
int ql;
int qlength = 0;
double totalQlength;
int time = 0;
bool available(); //checks availability of servers
int main() {
ifstream fin;
fin.open("Sample2.txt");
if (!fin.good())
cerr << "Couldn't find file/corrupted file" << endl;
fin >> serverCount; //reads number of servers and efficiency
//from file
for (int i = 0; i < serverCount; i++) {
server s;
fin >> s.effi;
s.status = true;
s.count = 0;
spq.insert(s);
}
//reads first event from file
event e;
fin >> e.eventTime;
fin >> e.serviceTime;
e.eventType = -1;
pq.insert(e);
int i = 1;
//while priority queue is not empty
while (!pq.isEmpty()) {
timeNow = pq.getArrivalTime(1);
while (time < pq.getArrivalTime(1)) {
totalQlength = totalQlength + list.getLength();
time++;
}
//get event from priority queue
if (pq.getServer(1) == -1) { //if arrival event, add to FIFO queue
list.AddTail(pq.getArrivalTime(1), pq.getServiceTime());
if (list.getLength() > qlength) {
qlength = list.getLength();
}
//read next arrival event from file
if (!fin.eof()) {
event e;
fin >> e.eventTime;
fin >> e.serviceTime;
e.eventType = -1;
pq.insert(e);
i++;
}
}
else //must be customer complete event
{
spq.setIdle(pq.getServer(1)); //set the server to idle
}
pq.deleteMin(); //remove the evnt from priority queue
//if FIFO queue is not empty and servers are available
//process event
if ((list.isEmpty() == false) && (available() == true)) {
list.getHead();
int s = spq.getMin();
spq.setBusy(s); //set server to busy
spq.incrementCustNumber(s); //increment number of customers
//served
double waitTime = timeNow - list.getHead().arrivalTime;
totalWait = totalWait + waitTime;
double serviceT = spq.getEffi(s) * list.getHead().serviceTime;
double eventT = list.getHead().arrivalTime +serviceT;
event e2;
e2.eventTime = eventT;
e2.serviceTime = list.getHead().serviceTime;
e2.eventType = s;
pq.insert(e2); //add customer complete event to the priority
//queue
list.RemoveHead(); //remove head from FIFO
}
totalTime = pq.getArrivalTime(1);
}
fin.close();
return 0;
}
bool available() {
bool ava = false;
for (int i = 1; i <= serverCount; i++) {
if (spq.getStatus(i) == true) {
ava = true;
break;
}
}
return ava;
}
Below is the priority queue implementation:
#include <iostream>
#include <fstream>
#include "PQueue.h"
using namespace std;
Pqueue::Pqueue() {
inde = 0; //length of heap
}
void Pqueue::insert(event i) { //inserts new element into the heap array and maintains min heap property
inde++;
pqueue[inde] = i;
siftup(inde);
}
int Pqueue::getServer(int i) {
return pqueue[i].eventType;
}
void Pqueue::siftup(int i) { //shifts element up to the correct position in the heap
if (i == 1)
return;
int p = i / 2;
if (pqueue[p].eventTime > pqueue[i].eventTime)
{
swap(pqueue[i], pqueue[p]);
siftup(p);
}
}
void Pqueue::deleteMin() { //removes element at the root of the heap
swap(pqueue[inde], pqueue[1]);
inde--;
siftdown(1);
}
void Pqueue::siftdown(int i) { //shifts element to its position in the min heap
int c = i * 2;
int c2 = (i * 2) + 1;
if (c > inde) return;
int in = i;
if (pqueue[i].eventTime > pqueue[c].eventTime)
{
in = c;
}
if ((c2 < inde) && (pqueue[i].eventTime > pqueue[c2].eventTime))
{
in = c2;
}
if (pqueue[c].eventTime < pqueue[c2].eventTime) {
in = c;
}
if (in != i) {
swap(pqueue[i], pqueue[in]);
siftdown(in);
}
}
void Pqueue::swap(event& i, event& j) {
event temp;
temp = i;
i = j;
j = temp;
}
bool Pqueue::isEmpty() { //checks if the priority queue is empty
if (inde == 0) return true;
else
return false;
}
double Pqueue::getArrivalTime(int i) {
return pqueue[i].eventTime;
}
double Pqueue::getServiceTime() {
return pqueue[1].serviceTime;
}
There are five servers with varying efficiency. The most efficient idle server is to be used. For this, I sorted the array of servers efficiency wise in the beginning.
#include <iostream>
#include <fstream>
#include "SPqueue.h"
using namespace std;
Spqueue::Spqueue() {
inde = 0;
}
void Spqueue::insert(server i) { //inserts new element into the array
inde++;
spqueue[inde] = i;
}
void Spqueue::heapify(int n, int i)
{
int largest = i; // Initialize largest as root
int l = 2 * i; // left = 2*i + 1
int r = 2 * i +1; // right = 2*i + 2
// If left child is larger than root
if (l < n && spqueue[l].effi > spqueue[largest].effi)
largest = l;
// If right child is larger than largest so far
if (r < n && spqueue[r].effi > spqueue[largest].effi)
largest = r;
// If largest is not root
if (largest != i)
{
swap(spqueue[i], spqueue[largest]);
// Recursively heapify the affected sub-tree
heapify(n, largest);
}
}
void Spqueue::heapSort()
{
// Build heap (rearrange array)
for (int i = inde / 2 - 1; i > 0; i--)
heapify(inde, i);
// One by one extract an element from heap
for (int i = inde - 1; i > 0; i--)
{
// Move current root to end
swap(spqueue[1], spqueue[i]);
// call max heapify on the reduced heap
heapify(i, 1);
}
}
void Spqueue::swap(server& i, server& j) {
server temp;
temp = i;
i = j;
j = temp;
}
int Spqueue::getMin() { //iterates to the next available server in the sorted list of servers
int i = 0;
while (i <=20){
if (spqueue[i].status == true)
{
return i;
}
else
{
i++;
}
}
}
bool Spqueue::getStatus(int i) {
return spqueue[i].status;
}
void Spqueue::setBusy(int i) {
spqueue[i].status = false;
}
void Spqueue::addServiceTime(int i,double s) {
spqueue[i].busyTime = spqueue[i].busyTime + s;
}
double Spqueue::getTotalServiceTime(int i) {
return spqueue[i].busyTime;
}
void Spqueue::setIdle(int i) {
spqueue[i].status = true;
}
double Spqueue::getEffi(int i) {
return spqueue[i].effi;
}
void Spqueue::incrementCustNumber(int i) {
spqueue[i].count++;
}
int Spqueue::getCount(int i) {
return spqueue[i].count;
}
And the following function is supposed to return the most efficient server.
int Spqueue::getMin() { //iterates to the next available server in
the already sorted array
int i = 0;
while (i <=20){
if (spqueue[i].status == true)
{
return i;
}
else
{
i++;
}
}
}
Your priority queue implementation of siftdown has some problems.
void Pqueue::siftdown(int i) { //shifts element to its position in the min heap
int c = i * 2;
int c2 = (i * 2) + 1;
// *** Possible bug
// *** I think that if c == inde, then c is indexing beyond the current queue
if (c > inde) return;
int in = i;
if (pqueue[i].eventTime > pqueue[c].eventTime)
{
in = c;
}
if ((c2 < inde) && (pqueue[i].eventTime > pqueue[c2].eventTime))
{
in = c2;
}
// ***************
// ** Bug here
if (pqueue[c].eventTime < pqueue[c2].eventTime) {
in = c;
}
if (in != i) {
swap(pqueue[i], pqueue[in]);
siftdown(in);
}
}
First, I think you want to test c1 >= inde. Also, when you're checking to see if pqueue[c].eventTime < pqueue[c2].eventTime, you do so without making sure that c2 is within bounds.
I find the following to be a more clear and succinct way to do things:
// find the smallest child
int in = c;
if (c2 < inde && pqueue[c2] < pqueue[c])
{
in = c2;
}
if (pqueue[in] < pqueue[i]) {
swap(pqueue[i], pqueue[in]);
siftdown(in);
}

Function pointer declared in struct for graph, assign same function

Basically i cant make work this logic simulator! I made an adjacency list that connects all the gates one to each other and then assign a value to them and AdjList that is the head should calculate the value using the function pointer. Problem is the only function it calls is And!(Xor Nand etc.. are never called)
The specific points are where pointer are initialized
struct AdjList
{
struct AdjListNode *head;
string GateName;
string OutputName;
bool result;
function <bool (vector <bool>)> ptrf;
};
and were they are assigned
if(i < Gate_IO.size() )
{
ptrPos = Gate_IO[i].find_first_of(' ');
switch (strtoi ( (Gate_IO[i].substr(0,ptrPos).c_str() )))
{
case strtoi("AND"):
{
VectorHeadPtr[i].ptrf = And;
break;
}
case strtoi("NAND"):
{
VectorHeadPtr[i].ptrf = Nand;
break;
}
case strtoi("OR"):
{
VectorHeadPtr[i].ptrf = Or;
break;
}
case strtoi("NOR"):
{
VectorHeadPtr[i].ptrf = Nor;
break;
}
case strtoi("XOR"):
{
VectorHeadPtr[i].ptrf = Xor;
break;
}
default:
break;
}
Then in function CalcGateValue() they are called to execute the program! it seems like they are recognised and assigned to the right value in VectorHeadPtr[i].ptrf i tried to cout in that point and it goes into that cycle but the only function called when i call CalcGateValue() is And! Am I missing something?
Here is the complete code:
#include <iostream>
#include <cstdlib>
#include <string>
#include <sstream>
#include <vector>
#include <algorithm>
#include <functional>
using namespace std;
int compare(string a, string b)
{
int n = count(a.begin(), a.end(), 'I');
int q = count(b.begin(), b.end(), 'I');
return n > q;
}
constexpr unsigned int strtoi(const char* str, int h = 0) //string to int for switch cycle
{
return !str[h] ? 5381:(strtoi(str, h+1)*33)^str[h];
}
bool Xor(vector<bool> inputs)
{ cout<<"Xor function called!"<<endl;
int counter = 0;
for (unsigned int i = 0;i < inputs.size(); i++)
{
if (inputs.at(i) == 1)
{
counter++;
}
}
if (counter % 2) //Xor gate gives output 1 if and odd number of 1 inputs is given
{
return 1;
}
else
{
return 0;
}
}
bool And(vector<bool> inputs) //static per richiamare la funzione dalla classe
{ cout<<"And function called!"<<endl;
for (int i = 0; i < (inputs.size()-1); i++)
{
if(inputs.at(i) == 0)
{
return 0;
}
}
return 1;
}
bool Nand(vector<bool> inputs)
{ cout<<"Nand function called!"<<endl;
return !And(inputs);
}
bool Or(vector<bool> inputs)
{cout<<"Or function called!"<<endl;
for (int i = 0; i < (inputs.size()-1); i++)
{
if (inputs.at(i) != inputs.at(i+1) )
{
return 1;
}
}
return inputs.at(0);//Any position it's ok because all nPoss are the same.
}
bool Nor(vector<bool> inputs)
{ cout<<"Nor function called!"<<endl;
return !Or(inputs);
}
/*
* Adjacency list node
*/
struct AdjListNode
{
int nPos;
bool gValue;
string name;
struct AdjListNode* next;
};
/*
* Adjacency list
*/
struct AdjList
{
struct AdjListNode *head;
string GateName;
string OutputName;
bool result;
function <bool (vector <bool>)> ptrf;
};
/**
* Class Graph
*/
class Graph
{
private:
int V;
int circInputs = 3;
int circOutputs = 2;
int circGates;
int PrimaryInputs = 0;
vector<string> ioPuts;
struct AdjList* VectorHeadPtr;
public:
Graph(vector<string> Gate_IO)
{
int ptrPos,cntr;
int cntrIO = 0;
int prevPrimaryInputs = 0;
bool flag_remove_duplicates = 0;
string GateToConnect;
circGates = Gate_IO.size();
V=Gate_IO.size() + circInputs + circOutputs; //nĀ°gates+input+output letti dal file
sort (Gate_IO.begin(), Gate_IO.end(), compare);
for (cntr = 0; cntr < (Gate_IO.size()-1) && (PrimaryInputs == prevPrimaryInputs); cntr++)
{
PrimaryInputs = count (Gate_IO[cntr+1].begin(), Gate_IO[cntr+1].end(), 'I');
prevPrimaryInputs = count (Gate_IO[cntr].begin(), Gate_IO[cntr].end(), 'I');
}
PrimaryInputs = cntr; //Here starts first N
for (int i = 0;i<Gate_IO.size();i++)
VectorHeadPtr = new AdjList [V];
for (int i = 0; i < V; i++)
{
if(i < Gate_IO.size() )
{
ptrPos = Gate_IO[i].find_first_of(' ');
switch (strtoi ( (Gate_IO[i].substr(0,ptrPos).c_str() )))
{
case strtoi("AND"):
{
VectorHeadPtr[i].ptrf = And;
break;
}
case strtoi("NAND"):
{
VectorHeadPtr[i].ptrf = Nand;
break;
}
case strtoi("OR"):
{
VectorHeadPtr[i].ptrf = Or;
break;
}
case strtoi("NOR"):
{
VectorHeadPtr[i].ptrf = Nor;
break;
}
case strtoi("XOR"):
{
VectorHeadPtr[i].ptrf = Xor;
break;
}
default:
break;
}
VectorHeadPtr[i].head = NULL;
stringstream ss;
ss << Gate_IO[i];
for (string temp; ss >> temp;)
{
if ( (temp.at(0)=='I') || (temp.at(0)=='O') && (temp!="OR") )
{
ioPuts.push_back(temp);
}
else if (temp.at(0) == 'U')
{
VectorHeadPtr[i].GateName=temp;
}
}
ptrPos = Gate_IO[i].find_last_of(' ');
VectorHeadPtr[i].OutputName = Gate_IO[i].substr(ptrPos);
}
else
{
if (flag_remove_duplicates == 0)
{
sort (ioPuts.begin(), ioPuts.end() );
ioPuts.erase (unique (ioPuts.begin(), ioPuts.end() ), ioPuts.end() );
flag_remove_duplicates = 1;
}
VectorHeadPtr[i].head = NULL;
VectorHeadPtr[i].ptrf = NULL;
VectorHeadPtr[i].GateName = ioPuts[cntrIO];
cntrIO++;
}
}
for (int i = 0; i < Gate_IO.size(); i++)
{
for(int j = 0; j < 2; j++)
{
ptrPos = Gate_IO[i].find_first_of(' ')+1;
Gate_IO[i].erase (0,ptrPos);
}
ptrPos = Gate_IO[i].find_last_of(' ')+1;
Gate_IO[i].erase( ptrPos);
stringstream ss;
ss << Gate_IO[i];
ss >> GateToConnect;
for (string temp; ss >> temp;)
{
addEdge(GateToConnect,temp);
}
}
}
/**
* Creates new adjacency list node for addEdge function
*/
AdjListNode* newAdjListNode(int nPos, string Name)
{
AdjListNode* newNode = new AdjListNode;
newNode->nPos = nPos;
newNode->name = Name;
newNode->next = NULL;
return newNode;
}
/**
* Add edge to graph
*/
void addEdge(string source, string destination)
{
int from, to;
for (int i = 0; i < V; ++i)
{
if ( (source == VectorHeadPtr[i].GateName) || (source == VectorHeadPtr[i].OutputName) )
{
from = i;
}
else if (( destination == VectorHeadPtr[i].GateName) || (destination == VectorHeadPtr[i].OutputName) )
{
to = i;
}
}
AdjListNode* newNode = newAdjListNode(to, destination);
newNode->next = VectorHeadPtr[from].head;
VectorHeadPtr[from].head = newNode;
}
/*
* Print the graph
*/
void printGraph()
{
for (int i = 0; i < circGates; i++)//meno ooutput+input
{
AdjListNode* Ptr = VectorHeadPtr[i].head;
cout<<endl<<"Gate connections for "<<VectorHeadPtr[i].GateName;
while (Ptr)
{
cout <<"-> "<< Ptr->name;
Ptr = Ptr->next;
}
cout<<" Output name is:"<<VectorHeadPtr[i].OutputName<<endl;
}
}
void calcGateVal()
{
vector<bool> Val={0, 1, 0};
vector<bool> Op;
for (int i = 0; i < circOutputs; i++)
{
ioPuts.pop_back();
}
for (int i = 0; i < circGates; i++)
{
AdjListNode* Ptr = VectorHeadPtr[i].head;
while (Ptr)
{
if (Ptr->name.at(0) == 'I')
{
for (int j = 0; j < ioPuts.size(); j++)
{
if (Ptr->name == ioPuts[j])
{
Ptr->gValue = Val[j];
}
}
}
Ptr = Ptr->next;
}
}
for (int i = 0; i < PrimaryInputs; i++)
{
AdjListNode* Ptr = VectorHeadPtr[i].head;
while (Ptr)
{
Op.push_back(Ptr->gValue);
Ptr = Ptr->next;
}
VectorHeadPtr[i].result = VectorHeadPtr[i].ptrf(Op);
cout<<"Gate Value is: "<<VectorHeadPtr[i].result<<" OutputName: "<<VectorHeadPtr[i].OutputName<<" GateName: "<<VectorHeadPtr[i].GateName<<endl;
Op.clear();
}
for (int i = PrimaryInputs; i < V; i++)
{
AdjListNode* Ptr = VectorHeadPtr[i].head;
while (Ptr)
{
for (int j = 0; j < PrimaryInputs; j++)
{
if (Ptr->name == VectorHeadPtr[j].OutputName)
{
Ptr->gValue = VectorHeadPtr[j].result;
}
}
Ptr = Ptr->next;
}
}
for (int i = PrimaryInputs; i < circGates; i++)
{
AdjListNode* Ptr = VectorHeadPtr[i].head;
while (Ptr)
{
Op.push_back(Ptr->gValue);
Ptr = Ptr->next;
}
VectorHeadPtr[i].result = VectorHeadPtr->ptrf(Op);
Op.clear();
}
}
void displayOutput()
{ cout<<endl;
for (int i = 0; i < circGates; i++)
{
cout<<"Value of outputs are ("<<VectorHeadPtr[i].GateName<<") "<<VectorHeadPtr[i].OutputName<<": "<<VectorHeadPtr[i].result<<endl;
}
}
};
/*
* Main
*/
int main()
{
vector<string> G_d;
G_d.push_back("AND 2 U0 I0 I1 N0");
G_d.push_back("XOR 2 U1 N0 I2 O0");
G_d.push_back("AND 2 U2 N0 I2 N1");
G_d.push_back("AND 2 U3 I0 I1 N2");
G_d.push_back("OR 2 U4 N1 N2 O1");
Graph gh(G_d);
gh.calcGateVal();
gh.displayOutput();
gh.printGraph();
// print the adjacency list representation of the above graph
return 0;
}
I think your code does not produce what you say it produces. Please see here:
http://coliru.stacked-crooked.com/a/405b04c8d9113790 - Check the output of this
Why do you want to convert strings to integers with strtoi with your case comparisons? :
case strtoi("NAND"):
a better approach would be strcmp or store each in a string perhaps a look up table and do a "==" equal equal comparison which is overloaded for strings.
Consider passing your vectors and objects around by reference rather than value, you might be expecting a return in your object but since you pass by value you never see them and this also avoids the overhead of making a copy of the vectors.

Memory leak concerns

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

Why I am getting zero output for all the values in array?

I got this implementation for maximum matching off the net and is trying to give its input through main class. But I am getting zero for all the places in match. What am I doing wrong?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <queue>
using namespace std;
void add_edge(int u, int v);
void edmonds();
struct edge {
int v, nx;
};
const int MAXN = 1000, MAXE = 2000;
edge graph[MAXE];
int last[MAXN], match[MAXN], px[MAXN], base[MAXN], N, M, edges;
bool used[MAXN], blossom[MAXN], lused[MAXN];
int main ()
{
// return 0;
add_edge(1,4);
add_edge(1,5);
add_edge(1,6);
add_edge(2,5);
add_edge(2,7);
add_edge(3,4);
add_edge(4,1);
add_edge(4,3);
add_edge(5,1);
add_edge(5,2);
add_edge(6,1);
add_edge(7,2);
edmonds();
cout << match[0];
cout << match[1];
cout << match[2];
cout << match[3];
cout << match[4];
cout << match[5];
cout << match[6];
}
inline void add_edge(int u, int v) {
graph[edges] = (edge) {v, last[u]};
last[u] = edges++;
graph[edges] = (edge) {u, last[v]};
last[v] = edges++;
}
void mark_path(int v, int b, int children) {
while (base[v] != b) {
blossom[base[v]] = blossom[base[match[v]]] = true;
px[v] = children;
children = match[v];
v = px[match[v]];
}
}
int lca(int a, int b) {
memset(lused, 0, N);
while (1) {
lused[a = base[a]] = true;
if (match[a] == -1)
break;
a = px[match[a]];
}
while (1) {
b = base[b];
if (lused[b])
return b;
b = px[match[b]];
}
}
int find_path(int root) {
memset(used, 0, N);
memset(px, -1, sizeof(int) * N);
for (int i = 0; i < N; ++i)
base[i] = i;
used[root] = true;
queue<int> q;
q.push(root);
register int v, e, to, i;
while (!q.empty()) {
v = q.front(); q.pop();
for (e = last[v]; e >= 0; e = graph[e].nx) {
to = graph[e].v;
if (base[v] == base[to] || match[v] == to)
continue;
if (to == root || (match[to] != -1 && px[match[to]] != -1)) {
int curbase = lca(v, to);
memset(blossom, 0, N);
mark_path(v, curbase, to);
mark_path(to, curbase, v);
for (i = 0; i < N; ++i)
if (blossom[base[i]]) {
base[i] = curbase;
if (!used[i]) {
used[i] = true;
q.push(i);
}
}
} else if (px[to] == -1) {
px[to] = v;
if (match[to] == -1)
return to;
to = match[to];
used[to] = true;
q.push(to);
}
}
}
return -1;
}
void build_pre_matching() {
register int u, e, v;
for (u = 0; u < N; ++u)
if (match[u] == -1)
for (e = last[u]; e >= 0; e = graph[e].nx) {
v = graph[e].v;
if (match[v] == -1) {
match[u] = v;
match[v] = u;
break;
}
}
}
void edmonds() {
memset(match, 0xff, sizeof(int) * N);
build_pre_matching();
register int i, v, pv, ppv;
for (i = 0; i < N; ++i)
if (match[i] == -1) {
v = find_path(i);
while (v != -1) {
pv = px[v], ppv = match[pv];
match[v] = pv, match[pv] = v;
v = ppv;
}
}
}
You set elements of match in two locations: In build_pre_matching() and in edmonds(). In both of these cases, no change will happen if match[x] for some index x isn't -1. The only other place elements of match get a value is during static initialization where the values get zero initialized. Since the initial value is zero and the values are only ever changed if at least one of them happens to be -1, I would expect that the values retain the value 0.
You might want to use something like
std::fill(std::begin(match), std::end(match), -1);
at a strategic location since you seem to assume that the values are initially -1. Of course, you also should consider the idea of not using global variables because this doesn't scale and works really badly in a multi-threaded program.