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);
}
}
Related
i tested the example in book <C++ Concurrency in Action> charpter 7 lock_free_queue and mutex_queue by 2 threads push and 2 threads pop ,the result is using mutex is faster than lock_free queue.here is the lock_free queue code.
so anyone can explain this result? on x86 cpu, the head and tail respectively of lock_free_queue is mutex free,so my first thought is this lock_free_queue will faster than mutex_queue .
here is the mutex queue code:
template<typename T>
class LockFreeQueue
{
public:
struct Node;
struct CountedNodePtr{
int external_count;
Node* ptr;
CountedNodePtr()noexcept:external_count(0),ptr(nullptr){}
};
std::atomic<CountedNodePtr> head;
std::atomic<CountedNodePtr> tail;
struct NodeCounter{
uint32_t internal_count:30;
uint32_t external_counters:2;
};
struct Node{
std::atomic<T*> data;
std::atomic<NodeCounter> count;
CountedNodePtr next;
Node()noexcept{
NodeCounter new_count;
new_count.external_counters = 2;
new_count.internal_count = 0;
count.store(new_count);
data.store(nullptr);
}
void ReleaseRef(){
NodeCounter old_counter = count.load(std::memory_order_relaxed);
NodeCounter new_counter;
do{
new_counter = old_counter;
--new_counter.internal_count;
}while(!count.compare_exchange_strong(old_counter, new_counter,
std::memory_order_acquire,std::memory_order_relaxed));
if(!new_counter.internal_count && !new_counter.external_counters){
delete this;
}
}
};
static void IncreaseExternalCount(std::atomic<CountedNodePtr>& counter,
CountedNodePtr& old_counter){
CountedNodePtr new_counter;
do{
new_counter = old_counter;
++new_counter.external_count;
}while(!counter.compare_exchange_strong(old_counter, new_counter,
std::memory_order_acquire,std::memory_order_relaxed));
old_counter.external_count = new_counter.external_count;
}
static void FreeExternalCounter(CountedNodePtr& old_node_ptr){
Node* const ptr = old_node_ptr.ptr;
int const count_increase = old_node_ptr.external_count-2;
NodeCounter old_counter = ptr->count.load(std::memory_order_relaxed);
NodeCounter new_counter;
do{
new_counter = old_counter;
--new_counter.external_counters;
new_counter.internal_count+=count_increase;
}while(!ptr->count.compare_exchange_strong(old_counter, new_counter,
std::memory_order_acquire,std::memory_order_relaxed));
if(!new_counter.internal_count && !new_counter.external_counters){
delete ptr;
}
}
public:
LockFreeQueue(){
CountedNodePtr ptr ;
ptr.external_count =1;
ptr.ptr = new Node;
head.store(ptr);
tail.store(head.load());
};
~LockFreeQueue(){
while(Node* const old_head = head.load().ptr){
head.store(old_head->next);
delete old_head;
}
}
void Push(T new_value){
std::unique_ptr<T> new_data = std::make_unique<T>(new_value);
CountedNodePtr new_next;
new_next.ptr = new Node;
new_next.external_count = 1;
CountedNodePtr old_tail = tail.load();
for(;;){
IncreaseExternalCount(tail,old_tail);
T* old_data = nullptr;
if(old_tail.ptr->data.compare_exchange_strong(old_data,
new_data.get())){
old_tail.ptr->next = new_next;
old_tail = tail.exchange(new_next);
FreeExternalCounter(old_tail);
new_data.release();
break;
}
old_tail.ptr->ReleaseRef();
}
}
std::unique_ptr<T> Pop(){
CountedNodePtr old_head = head.load(std::memory_order_relaxed);
for(;;){
IncreaseExternalCount(head,old_head);
Node* const ptr = old_head.ptr;
if(ptr==tail.load().ptr){
ptr->ReleaseRef();
return std::unique_ptr<T>();
}
if(head.compare_exchange_strong(old_head, ptr->next)){
T* const res = ptr->data.exchange(nullptr);
FreeExternalCounter(old_head);
return std::unique_ptr<T>(res);
}
ptr->ReleaseRef();
}
}
};
// here is the mutex_queue
template <typename T>
class ThreadSafeQueue {
public:
ThreadSafeQueue() {}
ThreadSafeQueue& operator=(const ThreadSafeQueue& other) = delete;
ThreadSafeQueue(const ThreadSafeQueue& other) = delete;
~ThreadSafeQueue() { BreakAllWait(); }
void Enqueue(const T& element) {
std::lock_guard<std::mutex> lock(mutex_);
queue_.emplace(element);
// cv_.notify_one();
}
bool Dequeue(T* element) {
std::lock_guard<std::mutex> lock(mutex_);
if (queue_.empty()) {
return false;
}
*element = std::move(queue_.front());
queue_.pop();
return true;
}
// bool WaitDequeue(T* element) {
// std::unique_lock<std::mutex> lock(mutex_);
// cv_.wait(lock, [this]() { return break_all_wait_ || !queue_.empty(); });
// if (break_all_wait_) {
// return false;
// }
// *element = std::move(queue_.front());
// queue_.pop();
// return true;
// }
typename std::queue<T>::size_type Size() {
std::lock_guard<std::mutex> lock(mutex_);
return queue_.size();
}
bool Empty() {
std::lock_guard<std::mutex> lock(mutex_);
return queue_.empty();
}
void BreakAllWait() {
break_all_wait_ = true;
// cv_.notify_all();
}
private:
volatile bool break_all_wait_ = false;
std::mutex mutex_;
std::queue<T> queue_;
struct Node{
int data;
Node * next;
Node(const int& d):data(d),next(NULL){}
};
// std::condition_variable cv_;
};
// test code added here
#include <iostream>
#include "lock_free_queue.h"
#include "thread_safe_queue.h"
#include "unbounded_queue.h"
#include <thread>
#include <chrono>
#include <thread>
#include <atomic>
#include <vector>
#include <mutex>
#include <utility>
#include <iomanip>
#include <ucontext.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <stddef.h>
#include <string.h>
#include <stdbool.h>
#include <stdint.h>
//#include <stdatomic.h>
#include <pthread.h>
#include <time.h>
#ifndef MDC_TEST
using namespace rudder::base;
using namespace apollo::cyber::base;
using namespace std;
struct Student
{
int a;
double b;
float c;
};
typedef int swr_ele_t; // 元素
int cycles;
typedef struct swr_queue
{ // 队列结构
std::atomic<size_t> head;
std::atomic<size_t> tail;
swr_ele_t *eles;
size_t size;
pthread_mutex_t lock;
} swr_queue_t;
LockFreeQueue<swr_ele_t> lock_queue_test[7];
ThreadSafeQueue<swr_ele_t> mutex_queue_test[7];
UnboundedQueue<swr_ele_t> unbounde_queue_test[7];
bool LockPush(const swr_ele_t *ele,int i)
{
lock_queue_test[i].Push(*ele);
return true;
};
bool LockPop(swr_ele_t *ele,int i)
{
auto tmp = lock_queue_test[i].Pop();
if(tmp == nullptr)
{
return false;
}
else
{
*ele = *tmp;
// std::cout<<"tmp"<<*tmp<<std::endl;
return true;
}
};
bool MutexPush(const swr_ele_t *ele,int i)
{
mutex_queue_test[i].Enqueue(*ele);
return true;
};
bool MutexPop(swr_ele_t *ele,int i)
{
swr_ele_t tmp;
if(mutex_queue_test[i].Dequeue(&tmp))
{
*ele = tmp;
return true;
}else{
return false;
}
};
bool UnboundedPush(const swr_ele_t *ele,int i)
{
unbounde_queue_test[i].Enqueue(*ele);
return true;
};
bool UnboundedPop(swr_ele_t *ele,int i)
{
swr_ele_t tmp;
if(unbounde_queue_test[i].Dequeue(&tmp))
{
*ele = tmp;
return true;
}else{
return false;
}
};
/***************************测试程序部分******************************/
typedef bool (*push_fn_t)(const swr_ele_t *,int);
typedef bool (*pop_fn_t)(swr_ele_t *,int);
// 线程参数
typedef struct thead_arg
{
//swr_queue_t *queue;
char type;
push_fn_t push;
pop_fn_t pop;
double push_time;
double pop_time;
int i;
} thead_arg_t;
// 计时器: 毫秒
double time_diff(struct timespec *start, struct timespec *end)
{
long sec = end->tv_sec - start->tv_sec;
long nsec = end->tv_nsec - start->tv_nsec;
return sec * 1000.0 + nsec / 1000000.0;
}
void *thread_func(void *a)
{
thead_arg_t *arg = (thead_arg_t *)a;
//swr_queue_t *queue = arg->queue;
struct timespec time1, time2;
clock_gettime(CLOCK_THREAD_CPUTIME_ID, &time1);
if (arg->type == 'W')
{ // Producer
swr_ele_t e = cycles;
while (true)
{
if (arg->push(&e,arg->i))
{
if ((--e) < 0)
break;
}
}
}
else
{ // Consumer
while (true)
{
swr_ele_t e;
// cout<<"arg->pop"<<std::endl;
if (arg->pop(&e,arg->i))
{
// cout<<"pop"<<e <<std::endl;
// if (e % 1000000 == 0) printf("pop ele: %d\n", e);
if (e == 0)
break;
}
}
}
clock_gettime(CLOCK_THREAD_CPUTIME_ID, &time2);
if(arg->type == 'W')
{
arg->push_time = time_diff(&time1, &time2);
}
else
{
arg->pop_time = time_diff(&time1, &time2);
}
printf("%c %d Time=%fms\n", arg->type, arg->i,time_diff(&time1, &time2));
// printf("%f ", arg->type, time_diff(&time1, &time2));
return NULL;
}
int main(int argc, char const *argv[])
{
// std::cout<<"argv"<< argv[1]<<std::endl;;
std::cout<<"core_num is : "<<std::thread::hardware_concurrency()<<std::endl;
std::cout<<"lock free head" <<lock_queue_test[0].head.is_lock_free()<<std::endl;
std::cout<<"lock free tail" <<lock_queue_test[0].tail.is_lock_free()<<std::endl;
int num = 0;
while(num<7)
{
cycles = 10000;
struct test_case
{
push_fn_t push;
pop_fn_t pop;
const char *desc;
} cases[] = {
//{LockPush, LockPop, "LockPush, LockPop"},
{MutexPush, MutexPop, "MutexPush,MutexPop"},
// {UnboundedPush, UnboundedPop, "UnboundedPush,UnboundedPop"},
};
for (unsigned int k = 0; k < sizeof(cases) / sizeof(cases[0]); ++k)
{
printf("----------------------------------------------------------------------------\n");
printf("%s\n", cases[k].desc);
swr_queue_t queue;
const int NUM = 6;
pthread_t tids[NUM];
thead_arg_t args[NUM];
int i;//0 1 2 3
// for (i = 0; i < NUM; ++i)
// {
// args[i].i = num;
// // args[i].queue = &queue;
// args[i].type = (i+1)%2 == 1 ? 'W' : 'R';
// args[i].push = cases[k].push;
// args[i].pop = cases[k].pop;
//// printf("pthread_create start");
// pthread_create(&tids[i], NULL, thread_func, args + i);
// }
for (i = 0; i < 3; ++i)
{
args[i].i = num;
// args[i].queue = &queue;
args[i].type = 'W';
args[i].push = cases[k].push;
args[i].pop = cases[k].pop;
// printf("pthread_create start");
pthread_create(&tids[i], NULL, thread_func, args + i);
// pthread_join(tids[i], NULL);
// printf("pthread_create %d",args[i].i);
}
for (i = 0; i < 3; ++i)
{
pthread_join(tids[i], NULL);
}
for (i = 3; i < 6; ++i)
{
args[i].i = num;
// args[i].queue = &queue;
args[i].type = 'R';
args[i].push = cases[k].push;
args[i].pop = cases[k].pop;
// printf("pthread_create start");
pthread_create(&tids[i], NULL, thread_func, args + i);
// pthread_join(tids[i], NULL);
// printf("pthread_create %d",args[i].i);
}
for (i = 3; i < 6; ++i)
{
pthread_join(tids[i], NULL);
}
printf("\n");
// printf("total time=%fms\n", args[0].push_time + args[1].pop_time);
// printf("%f\n", args[0].push_time + args[1].pop_time);
}
num++;
}
return 0;
}
#endif /* MDC_TEST */
I am getting this error message can anyone help me out.
I am getting the error code 'return' cannot convert from 'clsStack' to 'T' relating the two functions listed below.
Code is as follows
Class
template <class T>
class clsStack //this is the stack class that is used to handle the functions and any data that needs passing between functions
{
private:
clsStack* data;
int iTop;
int iSize;
void resize();
bool needToResize();
string sExpresion;
public:
void stack()
{
iSize = 5;
iTop = 0;
data = new clsStack[iSize];
}
void push(T item);
T peek();
T pop();
bool isEmpty();
};
The two functions I think the issue is related to
template <class T>
T clsStack<T>::peek() //this is used to look at the last number is the array
{
if (iTop <= 0)
throw out_of_range("Attempted to peek an empty stack. \n");
return data[iTop - 1];
}
template <class T>
T clsStack<T>::pop()
{
if (iTop <= 0)
throw out_of_range("Attempted to pop an empty stack. \n");
iTop++;
return data[iTop];
}
The main function where these functions are been called
int evaluate(string sExpresion)
{
clsStack<int> iValues;
clsStack<char> cOperators;
int iValue = 0;
int iPosition = 0;
bool bResult = false;
while (iPosition < sExpresion.length())
{
char cSpot = sExpresion[iPosition];
if (isDigit(cSpot))
{
iValue = (iValue * 10) + (int)(cSpot - '0');
}
else if (isOperator(cSpot))
{
if (cSpot == '(')
{
cOperators.push(cSpot);
iValue = 0;
}
if (cSpot == '-')
{
cOperators.push(cSpot);
iValue = 0;
}
else if (iValues.isEmpty() && cOperators.peek() == '-')
{
int iPrevValue = iValues.pop();
int iPrevOperator = cOperators.pop();
iPrevValue = operation(iValue, iPrevValue, iPrevOperator);
iValues.push(iPrevValue);
cOperators.push(cSpot);
}
else if (iValues.isEmpty())
{
iValues.push(iValue);
cOperators.push(cSpot);
iValue = 0;
}
else if (cSpot == ')')
{
iValues.push(iValue);
while (cOperators.peek() != '(')
{
cSpot = cOperators.pop();
iValue = iValues.pop();
int iPrev = iValues.pop();
iValue = operation(iPrev, iValue, cSpot);
iValues.push(iValue);
}
cOperators.pop();
iValues.pop();
}
else
{
int iPrevValue = iValues.pop();
int iPrevOperator = cOperators.pop();
iPrevValue = operation(iPrevValue, iValue, iPrevOperator);
iValues.push(iPrevValue);
cOperators.push(cSpot);
iValue = 0;
}
}
iPosition++;
}
while (!cOperators.isEmpty())
{
int iPrev = iValues.pop();
char cSpot = cOperators.pop();
iValue = operation(iPrev, iValue, cSpot);
bResult = true;
}
return (sExpresion, iValue, bResult);
}
Any help is much apricated.
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
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));
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. ;)