Memory leak concerns - c++

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

Related

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.

error C2352 illegal call of non-static member function

I am creating a Heap type priority queue using a dynamically sized array. I am aware that vectors would be simpler to implement, but this is a learning exercise for me. Everything works great, but I am having issues only when attempting some Unit testing in visual studio '13. I'm experiencing this error
Here is the source file where I attempt to run the Unit tests:
//Prog1Test.cpp
#include "UnitTest.h"
#include <iostream>
int main()
{
PriorityQueue Q = PriorityQueue();
UnitTest::test1(Q);
UnitTest::test2(Q);
UnitTest::test3(Q);
UnitTest::test4(Q);
return 0;
}
Here is the UnitTest.cpp:
//UnitTest.cpp
#include "UnitTest.h"
#include <cassert>
void UnitTest::test1(PriorityQueue Q)
{
Q.clear();
Q.append('a');
Q.append('b');
assert(Q.size() == 2);
assert(Q.check() == true);
}
void UnitTest::test2(PriorityQueue Q)
{
Q.clear();
Q.append('b');
Q.append('a');
assert(Q.size() == 2);
assert(Q.check() == false);
}
void UnitTest::test3(PriorityQueue Q)
{
Q.clear();
Q.insert('a');
Q.insert('b');
assert(Q.size() == 2);
assert(Q.check() == true);
assert(Q.remove() == 'a');
assert(Q.size() == 1);
}
void UnitTest::test4(PriorityQueue Q)
{
Q.clear();
Q.insert('b');
Q.insert('a');
assert(Q.size() == 2);
assert(Q.check() == true);
assert(Q.remove() == 'a');
assert(Q.size() == 1);
}
Here is the UnitTest header file:
//UnitTest.h
#ifndef UnitTest_H
#define UnitTest_H
#include "PriorityQueue.h"
class UnitTest
{
public:
void test1(PriorityQueue Q);
void test2(PriorityQueue Q);
void test3(PriorityQueue Q);
void test4(PriorityQueue Q);
};
#endif
Here is the PriorityQueue class header:
#ifndef PriorityQueue_H
#define PriorityQueue_H
class PriorityQueue
{
private:
char *pq;
int length;
int nextIndex;
char root;
public:
PriorityQueue();
~PriorityQueue();
char& operator[](int index);
void append(char val);
int size();
void clear();
void heapify();
bool check();
void insert(char val);
char remove();
friend class UnitTest;
};
#endif
here is the priorityqueue.cpp file:
#include<math.h>
#include "PriorityQueue.h"
PriorityQueue::PriorityQueue()
{
pq = new char[0];
this->length = 0;
this->nextIndex = 0;
}
PriorityQueue::~PriorityQueue() {
delete[] pq;
}
char& PriorityQueue::operator[](int index) {
char *pnewa;
if (index >= this->length) {
pnewa = new char[index + 1];
for (int i = 0; i < this->nextIndex; i++)
pnewa[i] = pq[i];
for (int j = this->nextIndex; j < index + 1; j++)
pnewa[j] = 0;
this->length = index + 1;
delete[] pq;
pq = pnewa;
}
if (index > this->nextIndex)
this->nextIndex = index + 1;
return *(pq + index);
}
void PriorityQueue::append(char val) {
char *pnewa;
if (this->nextIndex == this->length) {
this->length = this->length + 1;
pnewa = new char[this->length];
for (int i = 0; i < this->nextIndex; i++)
pnewa[i] = pq[i];
for (int j = this->nextIndex; j < this->length; j++)
pnewa[j] = 0;
delete[] pq;
pq = pnewa;
}
pq[this->nextIndex++] = val;
}
int PriorityQueue::size() {
return this->length;
}
void PriorityQueue::clear() {
delete[] pq;
pq = new char[0];
this->length = 0;
this->nextIndex = 0;
}
void PriorityQueue::heapify() {
char parent;
char root;
char temp;
for (double i = this->length - 1; i >= 0; i--)
{
root = pq[0];
int parentindex = floor((i - 1) / 2);
int leftchildindex = 2 * i + 1;
int rightchildindex = 2 * i + 2;
if (pq[(int)i] <= pq[leftchildindex] && pq[(int)i] <= pq[rightchildindex])
{
pq[(int)i] = pq[(int)i];
}
else if (rightchildindex < this->length && pq[(int)i] > pq[rightchildindex])
{
temp = pq[(int)i];
pq[(int)i] = pq[rightchildindex];
pq[rightchildindex] = temp;
heapify();
}
else if (leftchildindex < this->length && pq[(int)i] > pq[leftchildindex])
{
temp = pq[(int)i];
pq[(int)i] = pq[leftchildindex];
pq[leftchildindex] = temp;
heapify();
}
}
}
void PriorityQueue::insert(char val) {
char *pnewa;
if (this->nextIndex == this->length) {
this->length = this->length + 1;
pnewa = new char[this->length];
for (int i = 0; i < this->nextIndex; i++)
pnewa[i] = pq[i];
for (int j = this->nextIndex; j < this->length; j++)
pnewa[j] = 0;
delete[] pq;
pq = pnewa;
}
pq[this->nextIndex++] = val;
PriorityQueue::heapify();
}
bool PriorityQueue::check() {
char root;
root = pq[0];
for (int i = this->length - 1; i >= 0; i--)
{
if ((int)pq[i]< (int)root)
return false;
}
return true;
}
char PriorityQueue::remove() {
char root = pq[0];
char *qminus;
qminus = new char[this->length];
for (int i = 1; i<this->length; i++)
qminus[i - 1] = pq[i];
pq = qminus;
this->length -= 1;
PriorityQueue::heapify();
return root;
}
you need to declare your test methods as static
class UnitTest
{
public:
static void test1(PriorityQueue Q);
static void test2(PriorityQueue Q);
static void test3(PriorityQueue Q);
static void test4(PriorityQueue Q);
};
Note that the static methods can only refer to static data members, since there is no class instance when calling these methods.
you need an instance of UnitTest
PriorityQueue Q = PriorityQueue();
UnitTest t;
t.test1(Q);
t.test2(Q);
t.test3(Q);
t.test4(Q);
return 0;
Note that currently there's no good reason why your test functions are part of a class altogether.
Both previous answers are correct, a static or using object may solve the problem.
Another solution is to use namespace instead of class:
namespace UnitTest
{
void test1(PriorityQueue Q);
void test2(PriorityQueue Q);
void test3(PriorityQueue Q);
void test4(PriorityQueue Q);
};

Why I can not output paths of the maze?Who can tell me?Please

about data structures,why i can't output paths of the maze? I use the stack to storage the information of the current position.Read map of maze through a text file,if the position cant't pass
will be marker by "#",it is a wall.the way marker by "+". written in C++.
PS:My English is very poor.
//stack.h
#ifndef _STACK_H_
#define _STACK_H_
#include<iostream>
#include<stdlib.h>
const int SIZE = 81;
using namespace std;
typedef struct
{
int x;
int y;
}PosType;
typedef struct SElemType{
int ord;//steps
PosType seat;//coordinate
int di;//direction
}SElemType;
typedef struct SqStack{
SElemType *base;
SElemType *top;
int StackSize;
}SqStack;
void Init_S(SqStack &S)
{
S.base = new SElemType[SIZE];
if(!S.base)
exit(EXIT_FAILURE);
S.top = S.base;
S.StackSize = SIZE;
}
bool StackEmpty(SqStack S)
{
if(S.top = S.base)
return true;
return false;
}
void Push(SqStack &S,SElemType e)
{
SElemType *newbase;
if(S.top-S.base>=S.StackSize)
{
newbase = new SElemType[S.StackSize*2];
if(!S.base)
exit(EXIT_FAILURE);
for(int i(0);i<S.top-S.base;i++)
*(newbase+i) = *(S.base+i);
delete[]S.base;
S.base = newbase;
S.top = S.base+S.StackSize;
S.StackSize *= 2;
}
*(S.top)++ = e;
}
void Pop(SqStack &S,SElemType e)
{
if(StackEmpty(S))
cout<<"empty stack!\n";
else
e = *(--S.top);
}
#endif
//maze.cpp
#include<iostream>
#include<cstdlib>
#include<fstream>
#include"stack.h"
using namespace std;
const int m = 10;
const int n = 10;
typedef char MazeG[m][n];
void Show_MG(MazeG MG)
{
for(int i(0);i<m;i++)
{
for(int j(0);j<n;j++)
{
cout<<MG[i][j];
}
cout<<"\t\n";
}
}
PosType Next(PosType &pos,int di)
{
PosType repos;
switch(di)
{
case 0://north
repos.x = pos.x-1;
repos.y = pos.y;
break;
case 1://east
repos.x = pos.x;
repos.y = pos.y+1;
break;
case 2://south
repos.x = pos.x+1;
repos.y = pos.y;
break;
case 3://west
repos.x = pos.x;
repos.y = pos.y-1;
break;
default:
break;
}
return repos;
}
int MazePath(MazeG &MG,PosType begin,PosType end)
{
PosType curpos = begin;
SqStack S;
Init_S(S);
SElemType e;
e.ord = 0;
do{
if(MG[curpos.x][curpos.y]=='*')
{
MG[curpos.x][curpos.y] = '+';
e.seat = curpos;
e.di = 0;
e.ord++;
Push(S,e);
if(curpos.x==end.x&&curpos.y==end.y)
{
cout<<"此迷宫的一条路径如下:(+标记为路径)\n";//the path of maze:
cout<<"走了"<<e.di<<"步到达出口\n";//The number of steps walked
Show_MG(MG);
return 0;
}
else
curpos = Next(curpos,e.di);
}
else
if(!StackEmpty(S))
{
Pop(S,e);
e.ord--;
while(e.di==3&&!StackEmpty(S))
{
MG[curpos.x][curpos.y] = '#';
Pop(S,e);
e.ord--;
}
if(e.di<3)
{
e.di++;
Push(S,e);
e.ord++;
curpos = Next(curpos,e.di);
}
}
}while(!StackEmpty(S));
cout<<"此迷宫没有入口到出口的路径!\n";//no path of the maze
//return -1;
}
int main()
{
MazeG MG;
PosType begin,end;
begin.x = 1; begin.y = 1;
end.x = 8; end.y = 8;
ifstream fin;
fin.open("file.txt");
if(!fin.is_open())
{
cout<<"erorr file!!\n";
exit(EXIT_FAILURE);
}
if(fin.good())
{
for(int i(0);i<m;i++)
for(int j(0);j<n;j++)
fin>>MG[i][j];
}
cout<<"迷宫图为:(*代表能通过)\n";//map of maze:('*' is means through)
Show_MG(MG);
cout<<begin.x<<begin.y<<end.x<<end.y<<endl;
fin.close();
MazePath(MG,begin,end);
return 0;
}
This is wrong
bool StackEmpty(SqStack S)
{
if(S.top = S.base)
return true;
return false;
}
It should be this
bool StackEmpty(SqStack S)
{
if(S.top == S.base) // == not =
return true;
return false;
}
Use == for equality not =.
Now,I understand my the error of code is that I mismatch the data will be stored by stack.
I have changed my code,that's right.
//stack.h
SElemType Gettop(SqStack S)
{
if(!Empty_S(S))
return *(S.top-1);
}
//maze_path.cpp
do{
if(MG[curpos.x][curpos.y]=='*')
{
MG[curpos.x][curpos.y] = '+';
e.seat = curpos;
e.di = 0;
e.ord++;
Push(S,e);
if(curpos.x==end.x&&curpos.y==end.y)
{
cout<<"此迷宫的一条路径如下:(+标记为路径)\n";//the path of maze:
cout<<"走了"<<e.di<<"步到达出口\n";//The number of steps walked
Show_MG(MG);
return 0;
}
else
curpos = Next(curpos,e.di);
}
else
if(!StackEmpty(S))
{
if(e.di<3)
{
e.ord++;
curpos = Next(curpos,e.di);
}
else
{
MG[curpos.x][curpos.y] = '#';
Pop(S,e);
e = Gettop(S);
}
}
}while(!StackEmpty(S));

How do I make a circular queue thread-safe?

So my Enqueue and Dequeue functions are below. How do I take what I have and make it thread safe? I thought about using a mutex from Windows.h, but I'd like to not limit my program to Windows-only, if possible.
void Queue::Enqueue(int num){
//increase recorded size
size++;
//stick in num
numbers[nextSpace] = num;
//find the next available space
nextSpace = (++nextSpace) % maxSize;
}
int Queue::Dequeue(){
int temp;
temp = items[curSpace];
curSpace = (++curSpace) % maxSize;
size--;
return temp;
}
You can refer this code (with pthreads):
#include<pthread.h>
#define DEFAULT_SIZE 100
class circularQueue{
private:
int *m_queue;
int p_head;
int p_tail;
int m_cap;
pthread_mutex_t mp = PTHREAD_MUTEX_INITIALIZER;
public:
circularQueue(int size)
{
/*in case invalid input*/
if(size<0)
size = DEFAULT_SIZE ;
m_queue = new int[size];
p_head = 0;
p_tail = -1;
m_cap = 0;
pthread_mutex_init(&mp,NULL);
}
bool enqueue(int x)
{
bool res= false;
p_thread_mutex_lock(&mp);
/*queue is full*/
if(m_cap == size)
{
res = false;
}
else
{
m_queue[(++p_tail)%size)] = x;
++m_cap;
res = true;
}
p_thread_mutex_unlock(&mp);
return res;
}
int dequeue()
{
int res=0;
pthread_mutex_lock(&mp);
/*empty queue*/
if(m_cap == 0)
{
throw("empty queue!");
pthread_mutex_unlock(&mp);
}
else{
res = m_queue[p_head];
p_head = (p_head+1)%size;
}
pthread_mutex_unlock(&mp);
return res;
}
~virtual circularQueue()
{
delete[] m_queue;
m_queue = NULL;
pthread_mutex_destroy(&mp);
}
}

C++ pointer "losing" its value

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