I have a homework which is done with C++. I coded it using a Main.cpp and a header file (datastruct.h). Homework was done, compiled and run successfully; but submission rules allow me to use just one main.cpp. When I tried to include my code in header to main.cpp I get:
[main] C:\cygnus\cygwin-b20\H-i586-cygwin32\bin\g++.exe 1000 (0) handle_exceptions: Exception: STATUS_ACCESS_VIOLATION
[main] g++ 1000 (0) handle_exceptions: Dumping stack trace to g++.exe.core
Note that: My question is not just about this error, it is about I get this error only I embed my header code to main.cpp. When they are separated, it works fine.
Here is my main.cpp when header codes were not included:
#include <iostream>
#include <fstream>
#include "datastruct.h"
using namespace std;
int main(int argc, char *argv[])
{
Game myGame;
myGame.initializer(argv[1]);
cout << myGame.gamePlay();
myGame.cleaner();
return 0;
}
And here is "datastruct.h":
#ifndef DATASTRUCT_H
#define DATASTRUCT_H
#include <iostream>
#include <fstream>
using namespace std;
int abs(int k) {
if(k < 0) k = -k;
return k;
}
struct Card {
int value;
Card* prev;
};
struct Deck {
Card* top ;
int cardNum;
void addCard(int xd);
int dropCard();
void create();
void clear();
void print();
};
void Deck::clear(/* arguments */) {
Card *p;
while(top)
{
p = top;
top = top -> prev;
delete p;
}
}
int Deck::dropCard(/* arguments */) {
Card* cardPtr;
int returnVal = top -> value;
cardPtr = top;
top = top -> prev;
delete cardPtr;
cardNum--;
return returnVal;
}
void Deck::create() {
cardNum = 0;
top = NULL;
}
void Deck::addCard(int xd) {
Card* newCard;
newCard = new struct Card;
newCard -> value = xd;
newCard -> prev = top;
top = newCard;
cardNum++;
}
struct Game {
Deck* p1;
Deck* p2;
Deck* table;
Deck* bin;
void initializer(char* filename);
void cleaner();
void gamePrint();
void p1gives();
void p2gives();
int gamePlay();
};
int Game::gamePlay()
{
int cardTaken;
while (true)
{
if((p1->cardNum ==0) || (p2->cardNum ==0) || (table->cardNum ==0)) break;
cardTaken = table->dropCard();
if (cardTaken < 0) {
for (int i = 0; i < abs(cardTaken); i++) {
if(p1->top == NULL) break;
p1gives();
}
} else {
for (int i = 0; i < cardTaken; i++) {
if(p2->top == NULL) break;
p2gives();
}
}
if((p1->cardNum ==0) || (p2->cardNum ==0) || (table->cardNum ==0)) break;
cardTaken = table->dropCard();
if (cardTaken < 0) {
for (int i = 0; i < abs(cardTaken); i++) {
if((p1->top == NULL) || (p2->top == NULL)) break;
p2gives();
}
} else {
for (int i = 0; i < cardTaken; i++) {
if((p1->top == NULL) || (p2->top == NULL)) break;
p1gives();
}
}
}
return (bin -> cardNum);
}
void Game::p1gives()
{
if(p2 -> top == NULL)
p2 -> addCard(p1 -> dropCard());
else if (p1 -> top -> value > p2 -> top -> value)
p2 -> addCard(p1 -> dropCard());
else if (p1 -> top -> value <= p2 -> top -> value)
bin -> addCard(p1 -> dropCard());
}
void Game::p2gives()
{
if (p1 -> top == NULL)
p1 -> addCard(p2 -> dropCard());
else if(p2 -> top -> value > p1 -> top -> value)
p1 -> addCard(p2 -> dropCard());
else if(p2 -> top -> value <= p1 -> top -> value)
bin -> addCard(p2 -> dropCard());
}
void Game::cleaner()
{
p1 -> clear();
p2 -> clear();
table -> clear();
bin -> clear();
delete p1;
delete p2;
delete table;
delete bin;
}
void Game::initializer(char* filename)
{
ifstream myFile(filename);
int tableDeckCount, playerDeckCount;
myFile >> tableDeckCount;
myFile >> playerDeckCount;
p1 = new struct Deck;
p1 -> create();
p2 = new struct Deck;
p2 -> create();
table = new struct Deck;
table -> create();
bin = new struct Deck;
bin -> create();
for (int i = 0; i < tableDeckCount; i++) {
int x;
myFile >> x;
table -> addCard(x);
}
for (int i = 0; i < playerDeckCount; i++) {
int x;
myFile >> x;
p1 -> addCard(x);
}
for (int i = 0; i < playerDeckCount; i++) {
int x;
myFile >> x;
p2 -> addCard(x);
}
}
void Deck::print(/* arguments */) {
Card* traverse;
traverse = top;
while (traverse) {
cout << traverse -> value << " , " ;
traverse = traverse -> prev;
}
cout << endl;
}
void Game::gamePrint()
{
cout << "P1:" << endl;
p1 -> print();
cout << "P2:" << endl;
p2 -> print();
cout << "TABLE:" << endl;
table -> print();
cout << "BIN:" << endl;
bin -> print();
}
#endif
I need to include header into main.cpp but when I copy codes I get error. Can someone help me?
Expected work example:
>g++ -std=c++0x -Wall -Wextra -Werror main.cpp -o cardgame
>./cardgame example.game
1
example.game file:
1 3
-2
6
7
8
1
5
4
Run the compilation in elevated privileges on Windows? (right-click run as administrator) /edit. Right-click on sh.exe for cygwin and go to compatibility and check the box "run as administrator")
also, for reference to those who negatively voted: https://developer.qualcomm.com/forum/qdn-forums/mobile-technologies/multimedia-optimization-hexagon-sdk/toolsinstallation/27100
Related
I can't seem to iterate through all the nodes. It goes through only 1 or two nodes and fails to return true for any case. I want the program to iterator through the node multiple times to get all possible outcome, but still be Eulerian circuit. This is just a small example. To determine if it is Eulerian Circuit, it must pass through the edge only once. Whenever i tried the recursive function DFSUtil, it will stop at the first node or the 2nd node.
Example:
start = A
End = C
A connect to B
A connect to C
B connect to A
B connect to C
C connect to B
Result: 2 path
A -> B -> C -> B -> A -> C
A -> B -> A -> C -> B -> C
#include <iostream>
#include <string>
#include <string.h>
#include <sstream>
#include <stdio.h>
#include <stack>
#include <vector>
using namespace std;
unsigned int V;
class node
{
public:
string Enzyme;
vector<node> connection;
node(string Enzyme)
{
this->Enzyme = Enzyme;
}
bool isEulerCircuit();
bool isConnected();
string DFSUtil(unsigned int v,bool visited[]);
void add_edge(node &n)
{
connection.push_back(n);
cout << Enzyme << " connected to " << n.Enzyme << endl;
}
};
string node::DFSUtil(unsigned int v,bool visited[])
{
visited[v] = true;
vector<node>::iterator it;
string res;
for(it = connection.begin(); it != connection.end(); it++)
{
cout << (*it).Enzyme << endl;
if(!visited[v])
{
res+= (*it).Enzyme;
DFSUtil(v,visited);
}
}
return res;
}
bool node::isEulerCircuit()
{
if (isConnected() == false)
{
return false;
}
return true;
}
bool node::isConnected()
{
bool visited[V];
for(int i = 0; i < V; i++)
{
visited[i] = false;
}
int n=3;
DFSUtil(n,visited);
for (int i = 0; i < V; i++)
{
if (visited[i] == false)
{
return false;
}
}
return true;
}
int main()
{
vector<node> nod;
string A = "A";
string B = "B";
string C = "C";
nod.push_back(A);
nod.push_back(B);
nod.push_back(C);
for(int i = 0; i < nod.size(); i++)
{
V = i;
}
cout << endl;
nod[0].add_edge(nod[1]);
nod[0].add_edge(nod[2]);
nod[1].add_edge(nod[0]);
nod[1].add_edge(nod[2]);
nod[2].add_edge(nod[1]);
if(nod[0].isEulerCircuit())
{
cout << "HI" << endl;
}
else
{
cout << "BYE" << endl;
}
return 0;
}
I'm trying to implement AVL Tree in C++, but I'm stuck with the insertion, I have changed some things but nothing seemed to effectively solve the problem. I used Xcode's Address Sanitizer and I'm getting that error after inserting a second element into the tree:
Thread 1: Use of deallocated memory detected.
==3822==ERROR: AddressSanitizer: heap-use-after-free on address.....
This is the implementation of the tree so far:
RoadTree.hpp
#ifndef RoadTree_hpp
#define RoadTree_hpp
#include "Road.hpp"
class RoadTree {
private:
struct TreeNode {
Road *key;
TreeNode *rightChild;
TreeNode *leftChild;
int height;
TreeNode() : key(NULL), rightChild(NULL), leftChild(NULL), height(0) { }
TreeNode(Road *r) : key(r), rightChild(NULL), leftChild(NULL), height(0) { }
};
TreeNode *root;
int numberOfRoads;
int GetHeight(TreeNode *n) const;
void SimpleRightRotation(TreeNode *&n);
void DoubleRightRotation(TreeNode *&n);
void SimpleLeftRotation(TreeNode *&n);
void DoubleLeftRotation(TreeNode *&n);
void Insert(TreeNode *&n, Road *r);
void ClearTree(TreeNode *&n);
void PreOrder(TreeNode *n) const;
public:
RoadTree();
~RoadTree();
void Insert(Road *r);
Road *FindRoad(string destination);
void ListRoads();
void ClearTree();
void PreOrder();
inline int RoadCount() {
return numberOfRoads;
}
};
#endif /* RoadTree_hpp */
RoadTree.cpp
#include "RoadTree.hpp"
RoadTree::RoadTree() : root(NULL), numberOfRoads(0) { }
RoadTree::~RoadTree() {
ClearTree(root);
}
void RoadTree::Insert(Road *r) {
Insert(root, r);
}
int RoadTree::GetHeight(TreeNode *n) const {
if (n == NULL)
return -1;
else
return n->height;
}
void RoadTree::SimpleRightRotation(TreeNode *&n) {
TreeNode *tempNode = n->rightChild;
n->rightChild = tempNode->leftChild;
tempNode->leftChild = n;
n->height = 1 + max(GetHeight(n->leftChild), GetHeight(n->rightChild));
n = tempNode;
tempNode->height = 1 + max(n->height, GetHeight(tempNode->rightChild));
}
void RoadTree::DoubleRightRotation(TreeNode *&n) {
SimpleLeftRotation(n->rightChild);
SimpleRightRotation(n);
}
void RoadTree::SimpleLeftRotation(TreeNode *&n) {
TreeNode *tempNode = n->leftChild;
n->leftChild = tempNode->rightChild;
tempNode->rightChild = n;
n->height = 1 + max(GetHeight(n->leftChild), GetHeight(n->rightChild));
n = tempNode;
tempNode->height = 1 + max(n->height, GetHeight(n->leftChild));
}
void RoadTree::DoubleLeftRotation(TreeNode *&n) {
SimpleRightRotation(n->leftChild);
SimpleLeftRotation(n);
}
void RoadTree::ClearTree(TreeNode *&n) {
if (n != NULL) {
ClearTree(n->rightChild);
ClearTree(n->leftChild);
delete n;
}
n = NULL;
}
void RoadTree::Insert(TreeNode *&n, Road *r) {
if (n == NULL) {
n = new TreeNode(r);
numberOfRoads++;
} else {
if (r->GetDestination() < n->key->GetDestination()) {
Insert(n->leftChild, r);
if ((GetHeight(n->leftChild) - GetHeight(n->rightChild)) == 2) {
if (r->GetDestination() < n->leftChild->key->GetDestination())
SimpleLeftRotation(n);
else
DoubleLeftRotation(n);
}
} else if (r->GetDestination() > n->key->GetDestination()) {
Insert(n->rightChild, r);
if ((GetHeight(n->rightChild) - GetHeight(n->leftChild)) == 2) {
if (r->GetDestination() > n->rightChild->key->GetDestination())
SimpleRightRotation(n);
else
DoubleRightRotation(n);
}
} else if (r->GetDestination() == n->key->GetDestination())
n->key->SetRoad(r->GetDestination(), r->GetCost(), r->GetInfo());
}
n->height = 1 + max(GetHeight(n->leftChild), GetHeight(n->rightChild));
}
Road *RoadTree::FindRoad(string destination) {
TreeNode *n = root;
while (n != NULL) {
string current = n->key->GetDestination();
if (destination < current)
n = n->leftChild;
else if (destination > current)
n = n->rightChild;
else if (destination == current)
return n->key;
}
return NULL;
}
void RoadTree::PreOrder(TreeNode *n) const {
if (n != NULL) {
cout << " " << n->key->GetDestination() << " ";
PreOrder(n->leftChild);
PreOrder(n->rightChild);
}
}
void RoadTree::PreOrder() {
PreOrder(root);
}
void RoadTree::ListRoads() {
}
void RoadTree::ClearTree() {
ClearTree(root);
}
And this is the implementation of Road:
Road.hpp
#ifndef Road_hpp
#define Road_hpp
#include <iostream>
using namespace std;
class Road {
private:
string destination;
int cost;
string info;
public:
Road();
Road(string destination, int cost, string info);
inline string GetDestination() {
return destination;
}
inline int GetCost() {
return cost;
}
inline string GetInfo() {
return info;
}
};
#endif /* Road_hpp */
Road.cpp
#include "Road.hpp"
Road::Road() {
destination = "";
cost = 0;
info = "";
}
Road::Road(string destination, int cost, string info) {
this->destination = destination;
this->cost = cost;
this->info = info;
}
The only way I can insert more than 1 element is leaving the destructor blank, then no error shows, so I don't know what's causing it to fail. The error is showing up at the Insertion method, in the line that compares the elements in order to advance in the tree.
Update: Since this is part of a bigger project, I'm almost 100% sure that the problem isn't from the tree's implementation (I put the tree and Road class in a separate project and everything worked as intended). The full project has a class called Place, it has a name and info, as well as an AVL Tree for each place (where I store the place's roads). Those places are stored in a Hash Table (that I have implemented myself).
This is the implementation of the Place class:
Place.hpp
#ifndef Place_hpp
#define Place_hpp
#include <iostream>
#include "Road.hpp"
#include "RoadTree.hpp"
using namespace std;
class Place {
private:
string name;
string info;
RoadTree adjacentRoads;
public:
Place();
Place(string name, string info);
void InsertRoad(Road *r);
Road *FindRoad(string destination);
void ListRoads();
inline string GetName() {
return name;
}
inline string GetInfo() {
return info;
}
inline void SetPlace(string newName, string newInfo) {
name = newName;
info = newInfo;
}
inline void Write() {
cout << name << endl;
cout << "Info: " << info << endl;
}
};
Place.cpp
#include "Place.hpp"
Place::Place() {
name = "";
info = "";
}
Place::Place(string name, string info) {
this->name = name;
this->info = info;
}
void Place::InsertRoad(Road *r) {
adjacentRoads.Insert(r);
}
Road *Place::FindRoad(string destination) {
return adjacentRoads.FindRoad(destination);
}
void Place::ListRoads() {
adjacentRoads.ListRoads();
}
This is how I get a pointer from the Hash Table (if the full code is needed tell me):
Place *HashTable::Find(string key) {
unsigned long hashedKey = HashFunction(key);
list<Place>::iterator current;
for (current = table[hashedKey].begin(); current != table[hashedKey].end(); current++) {
Place currentPlace = *current;
if (currentPlace.GetName() == key)
return &*current;
}
return NULL;
}
And this is an example of a main that gives me the Thread 1: Use of deallocated memory detected. error
int main(int argc, const char * argv[]) {
//Declare a HashTable to store Places
HashTable map;
//Declare some places
Place p1("Murcia", "10");
Place p2("Lorca", "11");
Place p3("Cartagena", "12");
Place p4("Zaragoza", "13");
Place p5("Madrid", "14");
Place p6("Galicia", "15");
//Insert those places into the HashTable
map.Insert(p1);
map.Insert(p2);
map.Insert(p3);
map.Insert(p4);
map.Insert(p5);
map.Insert(p6);
//Declare some roads
Road *r1 = new Road(p2.GetName(), 20, "asdgasdg");
Road *r2 = new Road(p3.GetName(), 61, "asdgsw2");
//Get a pointer of a place from the HashTable to insert roads in it
Place *p1f = map.Find(p1.GetName());
//Check if it's not null, if it's not then insert the first road,
//get a pointer of it and print the name
if (p1f != NULL) {
p1f->InsertRoad(r1);
Road *r1f = p1f->FindRoad(p2.GetName());
cout << r1f->GetDestination() << endl;
}
//Get pointer of a place again (each time you want to insert a road
//in a place you must get it's pointer from the HashTable
Place *p2f = map.Find(p1.GetName());
//Checks again and insert second road, then throws error after that
if (p2f != NULL) {
p2f->InsertRoad(r2);
Road *r2f = p1f->FindRoad(p3.GetName());
cout << r2f->GetDestination() << endl;
}
return 0;
Update 2: Added HashTable implementation
HashTable.hpp
#ifndef HashTable_hpp
#define HashTable_hpp
#include "Place.hpp"
#include <list>
class HashTable {
private:
list<Place> *table;
int numberOfEntries;
int currentTableSize;
float maxLoadFactor;
unsigned int HashFunction(string key);
bool LoadFactorExceeded();
void ResizeTable();
bool IsPrime(int number);
int NextPrime(int number);
public:
HashTable();
~HashTable();
void Insert(Place p);
Place *Find(string key);
void EmptyTable();
void ListPlaces();
inline int Count() {
return numberOfEntries;
}
};
#endif /* HashTable_hpp */
HashTable.cpp
#include "HashTable.hpp"
#include <algorithm>
const int START_SIZE = 101;
HashTable::HashTable() {
table = new list<Place>[START_SIZE];
numberOfEntries = 0;
maxLoadFactor = 2.0f;
currentTableSize = START_SIZE;
for (int i = 0; i < START_SIZE; i++) {
table[i].clear();
}
}
HashTable::~HashTable() {
delete [] table;
}
unsigned int HashTable::HashFunction(string key) {
unsigned long hashValue = 0;
for (int i = 0; i < key.length(); i++)
hashValue = 47 * hashValue + key[i];
return (hashValue % currentTableSize);
}
bool HashTable::LoadFactorExceeded() {
float currentLoadFactor = numberOfEntries / currentTableSize;
if (currentLoadFactor > maxLoadFactor)
return true;
else
return false;
}
void HashTable::ResizeTable() {
list<Place> *oldTable = table;
int oldTableSize = currentTableSize;
currentTableSize *= 2;
currentTableSize = NextPrime(currentTableSize);
table = new list<Place>[currentTableSize];
for (int i = 0; i < currentTableSize; i++)
table[i].clear();
numberOfEntries = 0;
for (int i = 0; i < oldTableSize; i++) {
list<Place>::iterator current;
for (current = oldTable[i].begin(); current != oldTable[i].end(); current++)
Insert(*current);
}
delete [] oldTable;
}
bool HashTable::IsPrime(int number) {
if (number % 2 == 0 || number % 3 == 0)
return false;
int divisor = 6;
while (divisor * divisor - 2 * divisor + 1 <= number) {
if (number % (divisor - 1) == 0)
return false;
if (number % (divisor + 1) == 0)
return false;
divisor += 6;
}
return true;
}
int HashTable::NextPrime(int number) {
while (!IsPrime(++number)) {}
return number;
}
void HashTable::Insert(Place p) {
unsigned long hashedKey = HashFunction(p.GetName());
list<Place>::iterator current = table[hashedKey].begin();
if (!table[hashedKey].empty()) {
for (current = table[hashedKey].begin(); current != table[hashedKey].end(); current++) {
Place ¤tPlace = *current;
if (currentPlace.GetName() == p.GetName()) {
currentPlace.SetPlace(p.GetName(), p.GetInfo());
break;
} else if (current == --table[hashedKey].end()) {
table[hashedKey].push_back(p);
numberOfEntries++;
}
}
} else {
table[hashedKey].push_back(p);
numberOfEntries++;
}
if (LoadFactorExceeded())
ResizeTable();
}
Place *HashTable::Find(string key) {
unsigned long hashedKey = HashFunction(key);
list<Place>::iterator current;
for (current = table[hashedKey].begin(); current != table[hashedKey].end(); current++) {
Place currentPlace = *current;
if (currentPlace.GetName() == key)
return &*current;
}
return NULL;
}
void HashTable::EmptyTable() {
for (int i = 0; i < currentTableSize; i++) {
table[i].clear();
}
table = new list<Place>[START_SIZE];
numberOfEntries = 0;
currentTableSize = START_SIZE;
}
void HashTable::ListPlaces() {
list<string> places;
for (int i = 0; i < currentTableSize; i++) {
list<Place>::iterator current;
for (current = table[i].begin(); current != table[i].end(); current++)
places.push_back(current->GetName());
}
places.sort();
for (list<string>::iterator current = places.begin(); current != places.end(); current++)
cout << *current << endl;
cout << "Total: " << numberOfEntries << " lugares" << endl;
}
What could be causing the problem?
I'm not sure if this is it, but I noticed something: it looks like a linked list, and your recursive ClearTree function will attempt to free items repeatedly:
void RoadTree::ClearTree(TreeNode *&n) {
if (n != NULL) {
ClearTree(n->rightChild);
ClearTree(n->leftChild);
delete n;
}
n = NULL;
}
Assuming there are 2 elements in the list, and we call it with the first element:
ClearTree( firstElement );
It will then first
ClearTree(n->rightChild); // 2nd element
which in turn will first call
ClearTree(n->rightChild); // non-existing 3rd element: NOP
and proceed with
ClearTree(n->leftChild); // first element again
Maybe if you didn't get the error, this would recurse until you get a stack overflow?
You could simply remove the call to ClearTree(n->leftChild) to fix it; the function will recurse across the rightChild until it reaches the end, then delete the nodes from last to first when it backtracks.
Perhaps it's better to just iterate over the list: (untested, hope this works)
TreeNode * cur = n;
while ( cur != NULL )
TreeNode * next = n->rightChild;
delete cur;
cur = next;
}
n = NULL;
UPDATE
I've found the problem. Here's my debug output:
> g++ -O0 -g *cpp && gdb ./a.out
(gdb) r
Starting program: /home/kenney/roadtree/a.out
= INITIALIZING PLACES =
--> RoadTree[0x7fffffffe1a0] CONSTRUCTOR root: 0
--> RoadTree[0x7fffffffe1c0] CONSTRUCTOR root: 0
--> RoadTree[0x7fffffffe1e0] CONSTRUCTOR root: 0
--> RoadTree[0x7fffffffe200] CONSTRUCTOR root: 0
--> RoadTree[0x7fffffffe220] CONSTRUCTOR root: 0
--> RoadTree[0x7fffffffe240] CONSTRUCTOR root: 0
= INSERTING PLACES =
<-- RoadTree[0x7fffffffe340] DESTRUCTOR! root: 0
<-- RoadTree[0x7fffffffe360] DESTRUCTOR! root: 0
<-- RoadTree[0x7fffffffe380] DESTRUCTOR! root: 0
<-- RoadTree[0x7fffffffe3a0] DESTRUCTOR! root: 0
<-- RoadTree[0x7fffffffe3c0] DESTRUCTOR! root: 0
<-- RoadTree[0x7fffffffe3e0] DESTRUCTOR! root: 0
= CREATING ROADS =
These are the p1..p6 and the map.Insert(p1..p6). There's already a hint that something is wrong. Next this code is run:
cout << "= p1 =\n";
Place *p1f = map.Find(p1.GetName());
cout << "found " << p1f << " for " << p1.GetName() << "\n";
Producing this debug output:
= p1 =
<-- RoadTree[0x7fffffffe110] DESTRUCTOR! root: 0
found 0x6098f0 for Murcia
Then,
if (p1f != NULL) {
p1f->InsertRoad(r1);
Road *r1f = p1f->FindRoad(p2.GetName());
cout << r1f->GetDestination() << endl;
}
outputting this debug from RoadTree::Insert, indicating that the first if statement's 'then' is executed, assigning a new TreeNode to n:
n null, allocating.
--> TreeNode[0x609ad0] CONSTRUCTOR
allocated TreeNode 0x609ad0 key: 0x609a60 dest: Lorca
Lorca
So far so good, now the same again for p2. First the output of map.Find:
= p2 =
FINDING Murcia
<-- RoadTree[0x7fffffffe110] DESTRUCTOR! root: 0x609ad0
!!! RoadTree::ClearTree:: delete 0x609a60
<-- TreeNode[0x609ad0] DESTRUCTOR
found 0x6098f0 for Murcia
Next we continue to p2f->InsertRoad(r2); which is basically Place.adjacentroads.Insert aka RoadTree.insert:
n not null: 0x609ad0 key: 0x609af0
Note the address of n: this is the deleted TreeNode.
Here, the 'else' of the 'if' in RoadTree::Insert is taken since n != NULL:
if (r->GetDestination() < n->key->GetDestination()) {
is executed, causing:
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7b9126b in std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(std::string const&) ()
from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
(gdb) bt
#0 0x00007ffff7b9126b in std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(std::string const&) ()
from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#1 0x00000000004046b3 in Road::GetDestination (this=0x609af0) at Road.hpp:20
#2 0x0000000000405121 in RoadTree::Insert (this=0x609900, n=#0x609900: 0x609ad0, r=0x609ab0) at RoadTree.cpp:75
#3 0x0000000000404c0d in RoadTree::Insert (this=0x609900, r=0x609ab0) at RoadTree.cpp:15
#4 0x0000000000404845 in Place::InsertRoad (this=0x6098f0, r=0x609ab0) at Place.cpp:14
#5 0x000000000040401d in main (argc=1, argv=0x7fffffffe5f8) at main.cpp:63
(gdb)
The fault is apparent in the n->key->GetDestination() which attempts to return a copy of a string that is already deleted, causing a segfault because some pointers are already overwritten.
The problem is in HashTable::Find, which does this:
Place currentPlace = *current;
if (currentPlace.GetName() == key)
return &*current;
which constructs a Place copy on the stack that gets destroyed when the method returns. The private fields of Place also get destroyed, including the string name, which was attempted to be returned by Road::GetDestination().
Replacing it with this with this solves it:
if (current->GetName() == key)
return &*current;
I'm not sure this is the only fix needed, but it's a step.
I downloaded pre-build library from http://sourceforge.net/projects/pthreads4w/files/latest/download?source=typ_redirect.
I extracted it to the following directory:
C:\Users\Veena\Documents\pthread\pthreads-w32-2-9-1-release
I set following things:
In projects -> right click -> properties -> configuration properties -> C/C++ -> General -> Additional include directories -> "C:\Users\Veena\Documents\pthread\pthreads-w32-2-9-1-release\Pre-built.2\include"
In projects -> right click -> properties -> configuration properties -> linker -> General -> Additional library directories -> "C:\Users\Veena\Documents\pthread\pthreads-w32-2-9-1-release\Pre-built.2\lib\x86"
In projects -> right click -> properties -> configuration properties -> linker -> Input -> Additional dependencies ->
pthreadVC2.lib
pthreadVCE2.lib
pthreadVSE2.lib
In projects -> right click -> properties -> configuration properties -> linker -> All options -> Additional options ->
-lpthread
This is my code:
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
struct Node {
int data;
struct Node* next;
};
struct Node*head;
pthread_rwlock_t rwlock;
int numThreads;
int i, j;
float mInsert, mDelete, mMember;
int data[1000];
int test[10000];
long numberOfTotalOperations = 10000;
long numberOfInsertOperations;
long numberOfDeleteOperations;
long numberOfMemberOperations;
void *Process(void* rank);
int Member(int val);
int Insert(int val);
int Delete(int val);
long getCurrentTime(void);
int main(int argc, char* argv[]) {
if (argc != 5) {
printf("<member op fraction> <insert op fraction> <delete op fraction>");
exit(0);
}
mMember = strtod(argv[1], NULL);
mInsert = strtod(argv[2], NULL);
mDelete = strtod(argv[3], NULL);
numThreads = strtod(argv[4], NULL);
numberOfInsertOperations = mInsert * numberOfTotalOperations;
numberOfDeleteOperations = mDelete * numberOfTotalOperations;
numberOfMemberOperations = mMember * numberOfTotalOperations;
pthread_rwlock_init(&rwlock, NULL);
//data set : create with non-repeated random number
for (i = 0; i < 1000; i++) {
while (1) {
int temp = rand() % 65536;
int found = 0;
for (j = 0; j < i; j++) {
if (data[j] == temp) { found = 1; break; }
}
if (found == 0) { data[i] = temp; break; }
}
}
//test set
for (i = 0; i < 10000; i++) {
while (1) {
int temp = rand() % 65536;
int found = 0;
for (j = 0; j < i; j++) {
if (test[j] == temp) { found = 1; break; }
}
if (found == 0) { test[i] = temp; break; }
}
}
//----------------------------------------- Insert,Delete,Member
long thread;
pthread_t* thread_handles;
thread_handles = malloc(numThreads * sizeof(pthread_t));
for (thread = 0; thread < numThreads; thread++)
pthread_create(&thread_handles[thread], NULL, Process, (void*)thread);
for (thread = 0; thread < numThreads; thread++)
pthread_join(thread_handles[thread], NULL);
//--------
free(thread_handles);
return 0;
}
void *Process(void* rank) {
long my_rank = (long)rank;
int i, offset = (numberOfTotalOperations * my_rank) / numThreads;
int my_last_i = offset + (numberOfTotalOperations / numThreads);
long insert_op = numberOfInsertOperations / numThreads;
long delete_op = numberOfDeleteOperations / numThreads;
long member_op = numberOfMemberOperations / numThreads;
for (i = offset; i < my_last_i; i++) {
if (i < offset + insert_op) { //insert
pthread_rwlock_wrlock(&rwlock);
Insert(test[i]);
pthread_rwlock_unlock(&rwlock);
}
else if (i < offset + insert_op + delete_op) { //delete
pthread_rwlock_wrlock(&rwlock);
Delete(test[i]);
pthread_rwlock_unlock(&rwlock);
}
else {
pthread_rwlock_rdlock(&rwlock);
Member(test[i]);
pthread_rwlock_unlock(&rwlock);
}
}
return NULL;
}
int Insert(int value)
{
struct Node*curr_p = head;
struct Node*pred_p = NULL;
struct Node*temp_p;
while (curr_p != NULL && curr_p->data < value)
{
pred_p = curr_p;
curr_p = curr_p->next;
}
if (curr_p == NULL || curr_p->data > value)
{
temp_p = malloc(sizeof(struct Node));
temp_p->data = value;
temp_p->next = curr_p;
if (pred_p == NULL) /** New first node */
{
head = temp_p;
}
else
{
pred_p->next = temp_p;
}
return 1;
}
else /* value already in list*/
{
return 0;
}
}
int Member(int value)
{
struct Node*curr_p = head;
while (curr_p != NULL && curr_p->data < value)
{
curr_p = curr_p->next;
}
if (curr_p == NULL || curr_p->data > value)
{
return 0;
}
else
{
return 1;
}
}
int Delete(int value)
{
struct Node*curr_p = head;
struct Node*pred_p = NULL;
while (curr_p != NULL && curr_p->data < value)
{
pred_p = curr_p;
curr_p = curr_p->next;
}
if (curr_p != NULL && curr_p->data == value)
{
if (pred_p == NULL) /** deleting first node in list */
{
head = curr_p->next;
free(curr_p);
}
else
{
pred_p->next = curr_p->next;
free(curr_p);
}
return 1;
}
else /* Value isn't in list */
{
return 0;
}
}
I got following errors which exhibits, pthreads are not included:
1. IntelliSense: a value of type "void *" cannot be assigned to an entity of type "pthread_t *"
2. IntelliSense: a value of type "void *" cannot be assigned to an entity of type "Node *"
3. cannot convert from 'void *' to 'pthread_t *'
4. cannot convert from 'void *' to 'Node *'
What's wrong with my setup?
So, I'm just tried to compile your code and got the same error. It's because you should do explicit conversion void* pointer returned from malloc.
//thread_handles = malloc(numThreads * sizeof(pthread_t));
thread_handles = (pthread_t*)malloc(numThreads * sizeof(pthread_t)); // right one
//temp_p = malloc(sizeof(struct Node));
temp_p = (struct Node*)malloc(sizeof(struct Node)); // right one
In projects -> right click -> properties -> configuration properties -> linker -> All options -> Additional options -> -lpthread
It's wrong. Why did you do this?
In projects -> right click -> properties -> configuration properties -> linker -> Input -> Additional dependencies -> pthreadVC2.lib pthreadVCE2.lib pthreadVSE2.lib
You should link only one this *.lib file. Description from README file:
In general:
pthread[VG]{SE,CE,C}[c].dll
pthread[VG]{SE,CE,C}[c].lib
where:
[VG] indicates the compiler
V - MS VC, or
G - GNU C
{SE,CE,C} indicates the exception handling scheme
SE - Structured EH, or
CE - C++ EH, or
C - no exceptions - uses setjmp/longjmp
c - DLL compatibility number indicating ABI and API
compatibility with applications built against
a snapshot with the same compatibility number.
See 'Version numbering' below.
I attended a class of C++, not like all my students, I bought a Mac using xcode to run and edit my files. But recently there is a piece of code, that can be well ran in Ubuntu system, but in my mac, it kept giving me error.
the error appears in this line: char (*maze)[width] = reinterpret_cast (m_maze);
and there are 3 lines with the same above content. if you use the code in Ubuntu, it runs successfully, but in mac, it terminates and report 3 same errors.
the warn said: can not initialize a type of type 'char()[width]' with an rvalue of 'char()[width] '
Plz help
the code is about a mouse in a MAZE.
here are the codes:
#include <iostream>
#include <stdexcept>
#include <cstdlib>
#include <cstdio>
using namespace std;
const char MOUSE = '*';
const char WAY = ' ';
const char WALL = '#';
const char PASS = '.';
const char IMPASS = 'X';
typedef enum tag_Direction {
EDIR_RIGHT,
EDIR_DOWN,
EDIR_LEFT,
EDIR_UP
} EDIR;
class Stack {
public:
Stack (void) : m_top (NULL) {}
~Stack (void) {
for (Node* next; m_top; m_top = next) {
next = m_top -> m_next;
delete m_top;
}
}
void push (EDIR dir) {
m_top = new Node (dir, m_top);
}
EDIR pop (void) {
if (! m_top)
throw underflow_error ("Underflow of Stack!");
EDIR dir = m_top -> m_dir;
Node* next = m_top -> m_next;
delete m_top;
m_top = next;
return dir;
}
private:
class Node {
public:
Node (EDIR dir, Node* next) : m_dir (dir),
m_next (next) {}
EDIR m_dir;
Node* m_next;
};
Node* m_top;
};
class Mouse {
public:
Mouse (size_t x, size_t y) : m_x (x), m_y (y),
m_total (0), m_valid (0) {}
size_t getx (void) const {
return m_x;
}
size_t gety (void) const {
return m_y;
}
size_t gettotal (void) const {
return m_total;
}
size_t getvalid (void) const {
return m_valid;
}
void stepright (void) {
m_x++;
remember (EDIR_RIGHT);
}
void stepdown (void) {
m_y++;
remember (EDIR_DOWN);
}
void stepleft (void) {
m_x--;
remember (EDIR_LEFT);
}
void stepup (void) {
m_y--;
remember (EDIR_UP);
}
void stepback (void) {
switch (recall ()) {
case EDIR_RIGHT:
m_x--;
break;
case EDIR_DOWN:
m_y--;
break;
case EDIR_LEFT:
m_x++;
break;
case EDIR_UP:
m_y++;
break;
}
}
private:
void remember (EDIR dir) {
m_brain.push (dir);
m_total++;
m_valid++;
}
EDIR recall (void) {
EDIR dir = m_brain.pop ();
m_total++;
m_valid--;
return dir;
}
size_t m_x;
size_t m_y;
size_t m_total;
size_t m_valid;
Stack m_brain;
};
class Game {
public:
Game (size_t width, size_t height) :
m_width (width), m_height (height),
m_maze (new char[width * height]),
m_mouse (0, 1) {
if (height < 3)
throw invalid_argument ("The maze is too small!");
srand (time (NULL));
char (*maze)[width] = reinterpret_cast<char (*)[width]> (m_maze);**
for (size_t i = 0; i < height; i++)
for (size_t j = 0; j < width; j++)
if (i == m_mouse.gety () &&
j == m_mouse.getx ())
maze[i][j] = MOUSE;
else
if ((i == 1 && j < 4) ||
(i == height - 2 && j >width-5))
maze[i][j] = WAY;
else
if (i == 0 || i == height - 1 ||
j == 0 || j == width - 1)
maze[i][j] = WALL;
else
maze[i][j] =
rand () % 4 ? WAY : WALL;
}
~Game (void) {
if (m_maze) {
delete[] m_maze;
m_maze = NULL;
}
}
void run (void) {
for (show (); ! quit () && step (););
}
private:
void show (void) {
char (*maze)[m_width] = reinterpret_cast<char (*)[m_width]> (m_maze);
for (size_t i = 0; i < m_height; i++) {
for (size_t j = 0; j < m_width; j++)
cout << maze[i][j];
cout << endl;
}
cout << "Total steps:" << m_mouse.gettotal ()
<< ",Valid steps:" << m_mouse.getvalid ()
<< endl;
}
bool quit (void) {
cout << "Press<Q>to exit,Other keys to continue..."<<flush;
int ch = getchar ();
cout << endl;
return ch == 'Q' || ch == 'q';
}
bool step (void) {
char (*maze)[m_width] = reinterpret_cast<char (*)[m_width]> (m_maze);
size_t x = m_mouse.getx ();
size_t y = m_mouse.gety ();
if (x + 1 <= m_width - 1 && maze[y][x + 1] == WAY) {
maze[y][x] = PASS;
m_mouse.stepright ();
}
else
if (y + 1 <= m_height - 1 &&
maze[y + 1][x] == WAY) {
maze[y][x] = PASS;
m_mouse.stepdown ();
}
else
if (x - 1 >= 0 &&
maze[y][x - 1] == WAY) {
maze[y][x] = PASS;
m_mouse.stepleft ();
}
else
if (y - 1 >= 0 &&
maze[y - 1][x] == WAY) {
maze[y][x] = PASS;
m_mouse.stepup ();
}
else {
maze[y][x] = IMPASS;
m_mouse.stepback ();
}
x = m_mouse.getx ();
y = m_mouse.gety ();
maze[y][x] = MOUSE;
show ();
if (x == 0 && y == 1) {
cout << "I can't get out!cry~~~~" << endl;
return false;
}
if (x == m_width - 1 && y == m_height - 2) {
cout << "I am OUT!!!" << endl;
return false;
}
return true;
}
size_t m_width;
size_t m_height;
char* m_maze;
Mouse m_mouse;
};
int main (int argc, char* argv[]) {
if (argc < 3) {
cerr << "Method:" << argv[0] << " <width> <height>"
<< endl;
return -1;
}
try {
Game game (atoi (argv[1]), atoi (argv[2]));
game.run ();
}
catch (exception& ex) {
cout << ex.what () << endl;
return -1;
}
return 0;
}
char (*maze)[width] = reinterpret_cast<char (*)[width]> (m_maze);
is not standard: warning: ISO C++ forbids variable length array 'maze' [-Wvla].
You have to use
m_maze[y * width + x]
instead of
maze[y][x]
Background
Creating a dice game where the dice roll value should be stored in a Linked List.
Question
How should an implementation of Linked List be completed in C++? '
Example (What I have tried using struct instead of class)
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
struct Score {
int d1;
int d2;
int total;
int totals[13];
int value;
struct Score * next;
}
score_dice1, score_dice2, score_total, score_totals;
struct Score * ordered_insert(struct Score * , struct Score * );
int dice = 2;
void Randomize() {
srand((unsigned) time(NULL));
}
int Random(int Max) {
return (rand() % Max) + 1;
}
int main(int argc, char * argv[]) {
struct Score * myList = NULL;
if (argc == 2) {
int dice_rolls;
dice_rolls = atoi(argv[1]);
Randomize();
for (dice = 2; dice <= 12; dice++)
score_totals.totals[dice] = 0;
for (dice = 0; dice < dice_rolls; dice++) {
score_dice1.d1 = Random(6);
score_dice2.d2 = Random(6);
score_total.total = score_dice1.d1 + score_dice2.d2;
score_totals.totals[score_total.total]++;
}
for (dice = 1; dice <= 13; dice++) {
printf("%i %i\n\r", dice, score_totals.totals[dice]);
}
} else {
std::cout << "How many times should we roll the dice?" << '\n' <<
"One number please" << '\n';
}
return 0;
}
You probably want to use the STL, and include the std::list class. You should look at the methods for that class. I will show you how using the std::vector class.
Suppose you want to place the following into the list,
struct roll_t {
int dice1; //value of dice1
int dice2; //value of dice2
int total; //total of dice1+dice2
roll_t() dice1(0), dice2(0), total(0) { }
roll_t(int d1, int d2) : dice1(d1), dice2(d2), total(d1+d2) { };
};
Here is a C++ list reference
Here is an example with explanation
But, let me also add an example here,
#include <vector>
using namespace std;
int main(int argc, char* argv[])
{
vector<roll_t> dv;
roll_t rolls[13+1];
//suppose you have initialized totals[] here...
for( ndx=1; ndx<=12; ++ndx ) {
rolls[ndx] = roll_t.new(random(6),random(6));
}
//move totals to vector (convert to list left as exercise for poster)
int ndx;
for( ndx=1; ndx<=12; ++ndx ) {
dv.push_back(rolls[ndx]);
}
//traverse vector (convert to list, you will need iterator)
cout << "Loop by index:" << endl;
for(ndx=0; ndx < dv.size(); dv++)
{
cout << "["<<ndx<<"]"
<< dv[ndx].dice1 <<','<< dv[ndx].dice2 <<','<< dv[ndx].total << endl;
}
}
The above uses the STL, but maybe this question is for a class? And you need to roll your own linked list? I have linked to some stackoverflow answers,
I built one of those,
Trying to make linkedlist in C
Here is a description of single-linked list,
Singly-list insert to end of list
Here is a basic C++ dice game,
Basic C++ Dice game
Here is an explanation of how to sort a linked list by moving pointers,
Trying to Sort a Linked List only by Manipulating Pointers
Those should help.
Answer
Use a class to create the Linked List logic.
Example
linklist.h
#pragma once
#ifndef LINKLIST_H
#define LINKLIST_H
#include <iostream>
using namespace std;
class linklist {
private:
struct node {
int data;
node * link;
}* p;
public:
linklist();
void append(int num);
void add_as_first(int num);
void addafter(int c, int num);
void del(int num);
void display();
int count();
~linklist();
};
linklist::linklist() {
p = NULL;
}
void linklist::append(int num) {
node * q, * t;
if (p == NULL) {
p = new node;
p -> data = num;
p -> link = NULL;
} else {
q = p;
while (q -> link != NULL)
q = q -> link;
t = new node;
t -> data = num;
t -> link = NULL;
q -> link = t;
}
}
void linklist::add_as_first(int num) {
node * q;
q = new node;
q -> data = num;
q -> link = p;
p = q;
}
void linklist::addafter(int c, int num) {
node * q, * t;
int i;
for (i = 0, q = p; i < c; i++) {
q = q -> link;
if (q == NULL) {
cout << "\nThere are less than " << c << " elements.";
return;
}
}
t = new node;
t -> data = num;
t -> link = q -> link;
q -> link = t;
}
void linklist::del(int num) {
node * q, * r;
q = p;
if (q -> data == num) {
p = q -> link;
delete q;
return;
}
r = q;
while (q != NULL) {
if (q -> data == num)
{
r -> link = q -> link;
delete q;
return;
}
r = q;
q = q -> link;
}
cout << "\nElement " << num << " not Found.";
}
void linklist::display() {
node * q;
cout << endl;
for (q = p; q != NULL; q = q -> link)
cout << endl << q -> data;
}
int linklist::count() {
node * q;
int c = 0;
for (q = p; q != NULL; q = q -> link)
c++;
return c;
}
linklist::~linklist() {
node * q;
if (p == NULL)
return;
while (p != NULL) {
q = p -> link;
delete p;
p = q;
}
}
#endif
main.cc
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <list>
#include <vector>
#include "linklist.h"
struct score {
int d1;
int d2;
int total;
int totals[13];
}
score_dice1, score_dice2, score_total, score_totals;
int dice = 2;
void Randomize() {
srand((unsigned) time(NULL));
}
int Random(int Max) {
return (rand() % Max) + 1;
}
int main(int argc, char * argv[]) {
linklist ll;
if (argc == 2) {
int dice_rolls;
dice_rolls = atoi(argv[1]);
Randomize();
for (dice = 2; dice <= 12; dice++)
score_totals.totals[dice] = 0;
for (dice = 0; dice < dice_rolls; dice++) {
score_dice1.d1 = Random(6);
score_dice2.d2 = Random(6);
score_total.total = score_dice1.d1 + score_dice2.d2;
score_totals.totals[score_total.total]++;
}
for (dice = 1; dice <= 13; dice++) {
ll.append(score_totals.totals[dice]);
std::cout << ll.count() << '\n';
ll.display();
}
} else {
std::cout << "How many times should we roll the dice?" << '\n' <<
"One number please" << '\n';
}
return 0;
}