How to fix Segmentation Fault error when instantiating objects - c++

I'm working to create a few classes that work together to simulate functions for a rental car agency. I have the classes working and I can create objects of each of the classes, but when I try to run the following code I get a segmentation fault and I'm not sure why. Why am I getting a segmentation fault when I declare the objects in this order?
I've tried switching the order in which I declare the objects and the error goes away. If I declare two cars with just the Car() constructor, then the problem also goes away. If I remove any of the functions in either the Car or Sensor class, the error goes away.
PS: I asked this question a few days ago, and I included way too much code because I couldn't identify the error (far from complete, minimal, and verifiable), but this time I've narrowed it down as far as I can. I apologize if it's a lot of code, but I've removed all the code I can and if I remove any more of it the problem goes away.
Here's my main file:
#include "Car.h"
int main() {
char make[] = "Subaru", model[] = "Outback", name[] = "Brandon",
type[] = "radar";
Sensor sensors[3];
Sensor sensor1 = Sensor(type), sensor2 = Sensor(), sensor3 =
Sensor();
sensors[0] = sensor1;
sensors[1] = sensor2;
sensors[2]= sensor3;
Car car1 = Car();
Car car2 = Car(make, 155.81, sensors);
return 0;
}
My Car class:
#ifndef CAR_H
#define CAR_H
#include <iostream>
#include "MyString.h"
#include "Sensor.h"
using namespace std;
#define MAX_STR_SIZE 256
#define MAX_NUM_SNSRS 3
class Car {
public:
Car();
Car(char* make, float baseprice, Sensor* sensors);
void setMake(char* make);
void setBaseprice(float baseprice);
void setAvailable(bool available);
void setOwner(char* owner);
void updatePrice();
private:
char m_make[MAX_STR_SIZE];
Sensor m_sensors[MAX_NUM_SNSRS];
int m_numsensors;
float m_baseprice;
float m_finalprice;
bool m_available;
char m_owner[MAX_STR_SIZE];
};
#endif
#include "Car.h"
Car::Car() {
char dflt[] = {'\0'};
setMake(dflt);
setAvailable(true);
setOwner(dflt);
m_numsensors = 0;
setBaseprice(0.0);
}
Car::Car(char* make, float baseprice, Sensor* sensors) {
char dflt[] = {'\0'};
setMake(make);
setAvailable(true);
setOwner(dflt);
for(int i = 0; i < MAX_NUM_SNSRS; i++) {
(*(m_sensors + i)) = Sensor(*(sensors + i));
if(myStringCompare((sensors + i)->getType(), "none") != 0) {
m_numsensors++;
}
}
setBaseprice(baseprice);
}
void Car::setMake(char* make) {
myStringCopy(m_make, make);
}
void Car::setBaseprice(float baseprice) {
m_baseprice = baseprice;
updatePrice();
}
void Car::setAvailable(bool available) {
m_available = available;
}
void Car::setOwner(char* owner) {
myStringCopy(m_owner, owner);
}
void Car::updatePrice() {
float totSnsrPrice = 0.0;
for(int i = 0; i < m_numsensors; i++) {
totSnsrPrice += (m_sensors + i)->getCost();
}
m_finalprice = m_baseprice + totSnsrPrice;
}
My Sensor class:
#ifndef SENSOR_H
#define SENSOR_H
#include "MyString.h"
#define MAX_STR_SIZE 256
#define NUM_TYPES 5
class Sensor {
public:
Sensor();
Sensor(char* type);
char* getType();
float getCost();
void setType(char* type);
void setCost(float extraCost);
private:
char m_type[MAX_STR_SIZE];
float m_extracost;
};
#endif
#include "Sensor.h"
const char* validSensors[] = {"gps", "camera", "lidar", "radar",
"none"};
const float prices[] = {5.0, 10.0, 15.0, 20.0, 0.0};
Sensor::Sensor() {
char dflt[] = "none";
setType(dflt);
setCost(0.0);
}
Sensor::Sensor(char* type) {
int index = -1;
char dflt[] = "none";
for(int i = 0; i < NUM_TYPES; i++) {
if(myStringCompare(type, *(validSensors + i)) == 0) {
index = i;
}
}
if(index < 0) {
setType(dflt);
setCost(0.0);
} else {
setType(type);
setCost(*(prices + index));
}
}
char* Sensor::getType() {
return m_type;
}
float Sensor::getCost() {
return m_extracost;
}
void Sensor::setType(char* type) {
myStringCopy(m_type, type);
}
void Sensor::setCost(float extracost) {
m_extracost = extracost;
}
myStringCopy and myStringCompare are just the typical std::string copy and compare functions, we're just not allowed to use them (they are include in MyString.h, I've been using them for a while, so I know they work as intended).
I expect the output to be nothing, but still successful, instead of a segmentation fault. I cannot find the error anywhere, any help would be appreciated. Thanks!
Edit: Here's my string class, as asked:
#ifndef MYSTRING_H
#define MYSTRING_H
int myStringCompare(const char* str1, const char* str2);
char* myStringCopy(char* destination, const char* source);
#endif
#include "MyString.h"
int myStringCompare(const char* str1, const char* str2) {
int index = 0;
while(*(str1 + index) != '\0' || *(str2 + index) != '\0') {
if(*(str1 + index) < *(str2 + index)) {
return -1;
}
if(*(str1 + index) > *(str2 + index)) {
return 1;
}
index++;
}
return 0;
}
char* myStringCopy(char* destination, const char* source) {
int index = 0;
while(*(source + index) != '\0') {
*(destination + index) = *(source + index);
index++;
}
*(destination + index) = '\0';
return destination;
}

We don't have the full details on your string class, so this is hard to reproduce.
However, when you call sensors[0] = sensor1; you are copying your Sensor, but haven't defined an assignment operator (or copy constructor for that matter).
You also do this in the Car constructor with
(*(m_sensors + i)) = Sensor(*(sensors + i));
Now without the full details of your string class, I can give suggestions that might help.
First, you are doing a lot of copying when you set up the senors.
You can collapse this
Sensor sensors[3];
Sensor sensor1 = Sensor(type), sensor2 = Sensor(), sensor3 =
Sensor();
sensors[0] = sensor1;
sensors[1] = sensor2;
sensors[2]= sensor3;
down to
Sensor sensors[3]={{type}, {}, {}};
This might not solve the problem, but is less to look at.
Next, remove the setters. You can use delegating constructors to tie the two you have together, and avoid these.
This avoids some copies.
Look very carefully at what gets deep or shallow copied.
If you have two char * types,
char * word = "Hello";
char * another_word = word;
the second is a "shallow" copy. You need an equivalent of strcpy to actually make a different ("deep") copy of the string.

Related

How to fix: Exception thrown: read access violation. **_Pnext** was 0xFDFDFE05

I'm trying to "build" a house which contains rooms. My teacher told me to do it with composition. My idea was to generate as many Rooms objects as many rooms my house has. I tried it with the following code but in the house.cpp's constructor my for cycle runs only once than it crashes at the line rooms[i] = load; with Exception thrown: read access violation.
_Pnext was 0xFDFDFE05.
Here's my code:
main.cpp:
'''
#include <iostream>
#include "House.h"
#include "Rooms.h"
using namespace std;
int main()
{
Rooms basic("basic");
House house(basic,2);
house.setRooms();
house.setWhichroom(1);
cout << house.getRooms().getRoomname();
return 0;
}
'''
house.h:
'''
#pragma once
#include <iostream>
#include <string>
#include "Rooms.h"
using namespace std;
class House
{
Rooms* rooms;
unsigned roomcount;
unsigned whichroom = 0;
public:
House();
House(const Rooms&, unsigned);
House(unsigned);
~House();
void setRoomcount(unsigned);
unsigned getRoomcount()const;
void setWhichroom(unsigned );
unsigned getWhichroom()const;
void setRooms();
Rooms getRooms()const;
};
'''
house.cpp:
'''
#include "House.h"
House::House(const Rooms& load, unsigned rc)
{
roomcount = rc;
for (int i = 0; i < roomcount; i++)
{
rooms = new Rooms;
rooms[i] = load;
}
}
House::House(unsigned x):roomcount(x)
{
}
House::~House()
{
roomcount = 0;
delete rooms;
}
void House::setRoomcount(unsigned x)
{
roomcount = x;
}
unsigned House::getRoomcount() const
{
return roomcount;
}
void House::setWhichroom(unsigned x)
{
whichroom = x;
}
unsigned House::getWhichroom() const
{
return whichroom;
}
void House::setRooms()
{
for (unsigned i = 1; i <= roomcount; i++)
{
char c = i;
string s = "room";
s += c;
rooms[i].setRoomname(s);
}
}
Rooms House::getRooms() const
{
return rooms[whichroom];
}
'''
rooms.h:
'''
#pragma once
#include <iostream>
#include "Things.h"
using namespace std;
class Rooms
{
protected:
string roomname;
Things things;
public:
Rooms();
Rooms(string);
~Rooms();
void setRoomname(string);
string getRoomname()const;
void setThings();
unsigned getThings()const;
};
'''
rooms.cpp:
'''
#include "Rooms.h"
Rooms::Rooms()
{
}
Rooms::Rooms(string name)
{
roomname = name;
}
Rooms::~Rooms()
{
}
void Rooms::setRoomname(string name)
{
roomname = name;
}
string Rooms::getRoomname() const
{
return roomname;
}
void Rooms::setThings()
{
things.setOnoff();
}
unsigned Rooms::getThings() const
{
return things.getOnoff();
}
'''
The problem is in the House constructor, where you have
for (int i = 0; i < roomcount; i++)
{
rooms = new Rooms;
rooms[i] = load;
}
You will create one single Rooms object, but treat it as an array of multiple rooms.
You also create and create and create new Room objects each iteration of the loop, making you loose the earlier objects.
The simple solution, if you need to continue to use explicit memory handling yourself, is to allocate the objects once and before the loop:
rooms = new Rooms[roomcount];
for (int i = 0; i < roomcount; i++)
{
rooms[i] = load;
}
Since you now use new[] you must match it with a delete[] in the destructor. And you need to learn about the rules of three and five.
To simplify your code I implore you to use a std::vector instead, as that will make life so much simpler for you as a C++ programmer.

Vector member always zero size on call to member function that uses push_back to add to the vector member

What I am trying to do is add cards to a vector that is to be a Blackjack hand, but each time I enter the function that uses push_back to add a card to the vector, the vector starts out empty. The problem is in my Hand class in the addCardToHand function, and the same issue is present in the same class in my showHand function. I have whittled the code down as much as I could but still present a full working version with the issue. I cannot figure out why my Hand class treats the hand as brand new every time I call a function in the class. Please advise.
// Card.h
#ifndef CARD_H
#define CARD_H
#include <string>
#include <array>
class Card {
private:
int rank;
int suit;
int hardValue;
int softValue;
static const std::array<std::string,14> ranks;
static const std::array<std::string,5> suits;
public:
Card();
Card(int rank, int suit);
int getHardValue() const;
int getSoftValue() const;
std::string toString() const;
};
#endif
// Card.cpp
#include "Card.h"
const std::array<std::string,14> Card::ranks {"","A","2","3","4","5","6","7","8","9","10","J","Q","K"};
const std::array<std::string,5> Card::suits {"","C","D","H","S"};
Card::Card() : rank(0), suit(0) {
hardValue = 0;
softValue = 0;
}
Card::Card(int rank, int suit) : rank(rank), suit(suit) {
if (rank == 1) {
hardValue = 1;
softValue = 11;
}
else if (rank <= 10) {
hardValue = rank;
softValue = rank;
}
else {
hardValue = 10;
softValue = 10;
}
}
int Card::getHardValue() const {
return hardValue;
}
int Card::getSoftValue() const {
return softValue;
}
std::string Card::toString() const {
return ranks[rank] + suits[suit];
}
// Shoe.h
#ifndef SHOE_H
#define SHOE_H
#include <vector>
#include <random>
#include "Card.h"
class Shoe {
private:
int numDecksInShoe;
std::vector<Card> shoe;
static int currentCard;
static int maxDealCard;
static const unsigned long int seed;
static std::mt19937 randEng;
void renewShoe();
public:
Shoe();
explicit Shoe(int numDecksInShoe);
std::vector<Card> getShoe() const;
int getCurrentCard() const;
int getMaxDealCard() const;
void shuffle();
Card dealCard();
};
#endif
// Shoe.cpp
#include <ctime>
#include "Shoe.h"
const unsigned long int Shoe::seed = static_cast<unsigned long int>(std::time(nullptr));
std::mt19937 Shoe::randEng(seed);
int Shoe::currentCard = 0;
int Shoe::maxDealCard = 51;
Shoe::Shoe() {
}
Shoe::Shoe(int decksInShoe) {
numDecksInShoe = decksInShoe;
int count = 0;
for (int i = 0; i < numDecksInShoe; i++) {
for (int suit = 4; suit >= 1; suit--) {
for (int rank = 1; rank <= 13; rank++) {
Card card(rank,suit);
shoe.push_back(card);
count += 1;
}
}
}
currentCard = 0;
maxDealCard = count - 1;
}
std::vector<Card> Shoe::getShoe() const {
return shoe;
}
int Shoe::getCurrentCard() const {
return currentCard;
}
int Shoe::getMaxDealCard() const {
return maxDealCard;
}
void Shoe::shuffle() {
Card temp;
std::uniform_int_distribution<int> deckDist(0,numDecksInShoe*52-1);
int index;
for (int i = 0; i < numDecksInShoe*52; i++) {
do {
index = deckDist(randEng);
} while (index == i);
temp = shoe[index];
shoe[index] = shoe[i];
shoe[i] = temp;
}
std::uniform_int_distribution<int> maxDeal(10,41);
int tempMax = (numDecksInShoe-1)*52 - 1;
maxDealCard = tempMax + 51 - maxDeal(randEng);
}
Card Shoe::dealCard() {
if (currentCard == maxDealCard) {
renewShoe();
}
Card dealCard = shoe[currentCard];
currentCard += 1;
return dealCard;
}
void Shoe::renewShoe() {
Shoe newShoe(numDecksInShoe);
shoe = newShoe.getShoe();
shuffle();
}
here is my Hand class
// Hand.h
#ifndef HAND_H
#define HAND_H
#include <vector>
#include <string>
#include "Card.h"
class Hand {
private:
std::vector<Card> hand;
public:
Hand();
std::vector<Card> getHand() const;
void addCardToHand(Card card);
void clearHand();
Card revealBottomCard();
std::string showHand() const;
std::string peakHand() const;
};
#endif
// Hand.cpp
#include <iostream>
#include "Hand.h"
Hand::Hand() {
}
std::vector<Card> Hand::getHand() const {
return hand;
}
void Hand::addCardToHand(Card card) {
std::cout << card.toString() << std::endl;
hand.push_back(card);
}
void Hand::clearHand() {
hand.clear();
}
std::string Hand::showHand() const {
std::string returnString = "";
for (int i = hand.size()-1; i >= 1; i--) {
returnString += hand[i].toString() + "\n";
}
returnString += "XX\n";
return returnString;
}
std::string Hand::peakHand() const {
std::string returnString = "";
for (int i = hand.size()-1; i >= 0; i--) {
returnString += hand[i].toString() + "\n";
}
return returnString;
}
here is the Table class that has the code that calls the Hand class functions
// Table.h
#ifndef TABLE_H
#define TABLE_H
#include "Shoe.h"
#include "Player.h"
class Table {
private:
Shoe shoe;
public:
explicit Table(Shoe shoe);
Shoe getShoe() const;
void clearHand(std::vector<Player> players);
void dealHand(std::vector<Player> players);
};
#endif
// Table.cpp
#include <iostream>
#include "Table.h"
Table::Table(Shoe shoe) : shoe(shoe) {
}
Shoe Table::getShoe() const {
return shoe;
}
void Table::clearHand(std::vector<Player> players) {
for (Player &player : players) {
player.getHand().clearHand();
}
}
void Table::dealHand(std::vector<Player> players) {
for (int i = 0; i <= 1; i++) {
for (Player &player : players) {
player.getHand().addCardToHand(shoe.dealCard());
}
}
}
// Player.h
#ifndef PLAYER_H
#define PLAYER_H
#include "Hand.h"
class Player {
private:
std::string name;
Hand hand;
double money;
public:
explicit Player(std::string name, double money = 1000.0);
std::string getName() const;
Hand getHand() const;
double getMoney() const;
};
#endif
// Player.cpp
#include "Player.h"
Player::Player(std::string name, double money) : name(name), money(money) {
}
std::string Player::getName() const {
return name;
}
Hand Player::getHand() const {
return hand;
}
double Player::getMoney() const {
return money;
}
and finally here is a short driver that runs and displays the issue
// blackjack testing
#include <iostream>
#include "Player.h"
#include "Table.h"
int main() {
std::vector<Player> players {Player("Tom",1500.0),Player("Sue"),Player("Dave")};
Shoe shoe1(6);
Table table1(shoe1);
table1.dealHand(players);
for (Player player : players) {
std::cout << player.getName() << "'s hand\n";
std::cout << player.getHand().showHand() << "\n\n";
}
}
The output is below. I printed out the cards that were added to the hand vector (and then 'forgotten') and below that above the XX's, if everything were to work correctly you should see the 4, 5 and 6 of spades since I did not shuffle the deck. The XX's are to simulate face down bottom card.
AS
2S
3S
4S
5S
6S
Tom's hand
XX
Sue's hand
XX
Dave's hand
XX
Sorry for dumping all this code in here, but I wanted to provide a full working solution and this is as small as I could get it. Thanks for any help.
player.getHand().addCardToHand(...);
player.getHand() returns a temporary Hand object that's a copy of player.hand. Then you add a card to that temporary object. Then that temporary object dies, added card and all. player.hand remains unchanged. This line of code is an elaborate no-op.
To add on #Igor's answer, the best way to fix this should probably return a reference instead:
const Hand& Player::getHand() const {
return hand;
}
I made this a const because returning a non-const could (potentially) allow you to break constness of a constant Player object. That is just inviting potential bugs.
Because of this, you may want to add a non-const version too:
Hand& Player::getHand() {
return hand;
}
Now you can't modify a const Player object, yet modify it properly when you need to.

Initialize and declare dynamically multiple variables of random entities in a loop in C++

This is my code:
#include <cstdlib>
#include <ctime>
#include <stdio.h>
#include <vector>
#define ENTITY(A) entity##A
#define ALM(A) alm##A
struct TEntity{
private:
int sumx;
int sumy;
const char * rep;
int m_ix;
int m_iy;
public:
TEntity(int x, int y, int sum_x, int sum_y, const char * txt);
};
TEntity::TEntity(int x, int y, int sum_x, int sum_y, const char * txt) {
m_ix = x;
m_iy = y;
sumx = sum_x;
sumy = sum_y;
rep = txt;
}
class IAlmacenable {
private:
void * element;
public:
IAlmacenable(void * e);
IAlmacenable();
void * getValue();
};
IAlmacenable::IAlmacenable(void *e) {
element = e;
}
IAlmacenable::IAlmacenable() {
element = nullptr;
}
void * IAlmacenable::getValue() {
return element;
}
class TList {
private:
std::vector<IAlmacenable*> elementos;
int position;
public:
TList();
int Size();
int Push(IAlmacenable* psz);
};
TList::TList() {
elementos = std::vector<IAlmacenable*>();
position = 0;
}
int TList::Size() {
return elementos.size();
}
int TList::Push(IAlmacenable* psz) {
int res = 0;
if (elementos.size() >= elementos.max_size()) {
res = -1;
}
else {
elementos.push_back(psz);
}
return res;
}
int main(){
srand(time(NULL));
TList *list = new TList();
//we can put entities in the list and the rest will be filled up to 5
int size = list->Size();
for(int i = size; i<5;i++){
const char c[] = {(rand() % 2 ? 65 + rand() % 25 : 97 + rand() % 25), '\0'};
TEntity ENTITY(i)(rand() % 10, rand() % 10, rand() % 5, rand() % 5, c);
IAlmacenable ALM(i)(&ENTITY(i));
list->Push(&ALM(i));
size++;
}
//do things like printing their value...
delete list;
return 0;
}
I need to create a new variable everytime it run the "TEntity ENTITY(i)" line,
the problem is that it creates the same variable always, I think it is because it creates the variable entityi and therefore it is overwriting on the same variable, besides it seems that the random it generates is always the same number since all entities have the same values ​​in all its parameters. The c variable create a const char * random variable between a-z, A-Z , I don't put the print code because it is unnecessary, so what can I do? Is there any way to dynamically create variables of entities whose values ​​are random?
EDIT
Here is the new code fixed (the macros have been eliminated since they were not necessary and the necessary code has been included to be able to execute it) but there is still the same problem that they are generated with the same parameters (since they are still the same variable):
#include <cstdlib>
#include <ctime>
#include <stdio.h>
#include <vector>
#include <conio.h>
#include <windows.h>
struct TEntity{
private:
int sumx;
int sumy;
const char * rep;
int m_ix;
int m_iy;
public:
TEntity(int x, int y, int sum_x, int sum_y, const char * txt);
void movimiento();
void pinta();
};
TEntity::TEntity(int x, int y, int sum_x, int sum_y, const char * txt) {
m_ix = x;
m_iy = y;
sumx = sum_x;
sumy = sum_y;
rep = txt;
}
void TEntity::movimiento() {
m_ix += sumx;
m_iy += sumy;
}
void TEntity::pinta() {
gotoxy(static_cast<short int>(m_ix), static_cast<short int>(m_iy));
printf("%s", rep);
}
void gotoxy(short int x, short int y)
{
COORD pos = {x, y};
HANDLE output = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(output, pos);
}
void clear()
{
system("cls");
}
class IAlmacenable {
private:
void * element;
public:
IAlmacenable(void * e);
IAlmacenable();
void * getValue();
};
IAlmacenable::IAlmacenable(void *e) {
element = e;
}
IAlmacenable::IAlmacenable() {
element = nullptr;
}
void * IAlmacenable::getValue() {
return element;
}
class TList {
private:
std::vector<IAlmacenable*> elementos;
int position;
public:
TList();
int Size();
int Push(IAlmacenable* psz);
IAlmacenable* First();
IAlmacenable* Next();
};
TList::TList() {
elementos = std::vector<IAlmacenable*>();
position = 0;
}
int TList::Size() {
return elementos.size();
}
int TList::Push(IAlmacenable* psz) {
int res = 0;
if (elementos.size() >= elementos.max_size()) {
res = -1;
}
else {
elementos.push_back(psz);
}
return res;
}
IAlmacenable* TList::First() {
IAlmacenable* res;
if (elementos.empty()) {
res = nullptr;
}
else {
res = elementos.front();
position = 1;
}
return res;
}
IAlmacenable* TList::Next() {
IAlmacenable* res;
if (elementos.empty()) {
res = nullptr;
}
else {
int pos = position;
int size = elementos.size();
if (pos < size) {
res = elementos.at(position);
position++;
}
else {
res = this->First();
}
}
return res;
}
int main(){
srand(time(NULL));
TList *list = new TList();
//we can put entities in the list and the rest will be filled up to 5
int size = list->Size();
for(int i = size; i<5;i++){
const char c[] = {(rand() % 2 ? 65 + rand() % 25 : 97 + rand() % 25), '\0'};
TEntity *entity = new TEntity(rand() % 10, rand() % 10, rand() % 5, rand() % 5, c);
IAlmacenable *alm = new IAlmacenable(entity);
list->Push(alm);
size++;
}
while(true){
clear();
for (int i = 0; i < size; i++) {
reinterpret_cast<TEntity *>(list->Next()->getValue())->pinta();
reinterpret_cast<TEntity *>(list->Next()->getValue())->movimiento();
}
Sleep(2000);
}
delete list;
return 0;
}
There is some confusion here.
Some points:
The macro is not fit-for-purpose, as you already know; you're just creating a variable name entityi each time;
That doesn't matter! The object only exists for the duration of the loop iteration anyway; C++ doesn't let you create multiple objects with the same name at the same time. In fact you can get rid of the entire macro stuff and just call the object entity;
Now that that's out of the way, you're getting repeated results because you're storing a pointer to each iteration of that local variable — on each occasion, that's a dangling pointer to an object that's been destroyed. Don't store dangling pointers!
You can either:
Dynamically allocate the objects that you're adding to the list, or
Store actual objects rather than pointers-to-objects.
Either way, the local-scope name is irrelevant and certainly need not change repeatedly for each loop iteration.

C++ - Segmentation fault when returning a string

I have this class
#include "Room.h"
#include "Book.h"
#include <cstdlib>
#include <iostream>
static int book_counter = 100;
//Constructors
Book::Book() {
for(int i = 0; i < 13; i++) {
this->customer_name += 97 + rand() % 26;
}
this->arrival = rand() % 30;
this->duration = 1 + (rand() % 10);
this->ppl = 1 + rand() % 5;
this->room = nullptr;
this->book_code = book_counter++;
}
Book::Book(std::string nm, int arr, int dur, int ppl) {
this->customer_name = nm;
this->arrival = arr;
this->duration = dur;
this->ppl = ppl;
this->room = nullptr;
this->book_code = book_counter++;
}
//Methods
int Book::getArr() {
return arrival;
}
int Book::getDur() {
return duration;
}
int Book::getPpl() {
return ppl;
}
void Book::anathesi(Room* x) {
this->room = x;
}
int Book::getBookCode() {
return book_code;
}
Room* Book::getRoom() {
return room;
}
std::string Book::getCustomerName() {
return customer_name;
}
which includes a string getter method getCustomerName().
When I call this method on main, via an instance created via the first constructor, everything works fine. On the other hand, if the instance is created via the second constructor, the method will cause a segmentation fault.
It seems like customer_name has an infinite length, thus causing a segmentation fault when I try to return it.
The method is called in main with this line of code:
cout << hotel.getBooks(i)->getBookCode() << " " << hotel.getBooks(i)->getCustomerName()
<< " " << hotel.getBooks(i)->getRoom()->getRoomCode() << "\n";
I am new into C++, so please elaborate my fault as much as needed.
The header file for class Book:
#ifndef PROJECT_BOOK_H
#define PROJECT_BOOK_H
#include <string>
class Room;
class Book {
protected:
std::string customer_name;
int book_code;
int arrival;
int duration;
int ppl;
Room* room;
public:
Book();
Book(std::string nm, int arr, int dur, int ppl);
void anathesi(Room* x);
int getArr();
int getDur();
int getPpl();
int getBookCode();
std::string getCustomerName();
Room* getRoom();
};
#endif //PROJECT_BOOK_H
In Hotel.h:
private: std::vector<Book*> books;
public: Book* getBooks(int i);
In Hotel.cpp:
Book* Hotel::getBooks(int i) {
return books[i];
}
Found the problem and fixed it.
I was creating instances with this piece of code:
Book obj(onoma, afiksh - 1, meres, arithmos);
which caused the segmentation I said.
I changed this to:
Book *obj = new Book(onoma, afiksh - 1, meres, arithmos);
and fixed the problem. Thanks for your time and help.
Unfortunately, I don't really know why this works, but it does, everything functions properly. Therefore I guess I'll have to look at new documentation.

C++ object member integer has ridiculous value (WTF)

This is for a poker game and I have class PokerTable defined in PokerTable.h
#include <iostream>
using namespace std;
class PokerTable
{
private:
int numPlayers;
int numPlaying;
int dealerPos;
int bigBlind;
int potSize;
int betSize;
bool flop;
bool turn;
bool river;
public:
//constructors
PokerTable();
PokerTable(int,int,int,int,int,bool,bool,bool);
//getters
int getNumPlayers(){return numPlayers;};
int getDealerPos(){return dealerPos;};
int getBigBlind(){return bigBlind;};
int getNumPlaying(){return numPlaying;};
int getPotSize(){return potSize;};
int getBetSize(){return betSize;};
bool getFlop(){return flop;};
bool getTurn(){return turn;};
bool getRiver(){return river;};
//void buttonShow(int);
//setters
void setBetSize(int inBetSize){betSize = inBetSize;};
void setBigBlind(int inBigBlind){bigBlind = inBigBlind;};
void setNumPlaying(int inNumPlaying){numPlaying = inNumPlaying;};
void setPotSize(int inPotSize){potSize = inPotSize;};
void setFlop(bool inFlop){flop = inFlop;};
void setTurn(bool inTurn){turn = inTurn;};
void setRiver(bool inRiver){river = inRiver;};
void setNumPlayers(int inPlayers){numPlayers = inPlayers;};
void setDealerPos(int inDealerPos){dealerPos = inDealerPos;};
};
PokerTable::PokerTable()
{
numPlayers = 9;
numPlaying = 9;
dealerPos = 1;
bigBlind = 20;
flop = false;
turn = false;
river = false;
}
PokerTable::PokerTable(int playerNum, int playingCount, int posDealer, int blindBig,int inPotSize, bool inFlop,bool inTurn,bool inRiver)
{
numPlayers = playerNum;
numPlaying = playingCount;
dealerPos = posDealer;
potSize = inPotSize;
bigBlind = blindBig;
flop = inFlop;
turn = inTurn;
river = inRiver;
}
In my watch list pokerTable.numPlayers has a random value up to 4 million before I even execute this next line of code.
PokerTable aPokerTable(9,9,1,20,30,false,false,false);
and afterwards here is pokerTable in my watch list:
- aPokerTable { numPlayers=2990892 numPlaying=9 dealerPos=9 ...} PokerTable
betSize 30 int
bigBlind 1 int
dealerPos 9 int
flop false bool
numPlayers 2990892 int
numPlaying 9 int
potSize 20 int
river false bool
turn false bool
Can anyone tell me why all the values are not what I declared them to be??!?!!
And how I can fix this?
This is Form1.h
#pragma once
#include "PokerTable.h"
#include "Card.h"
#include <time.h>
#include "PokerPlayer.h"
#include <fstream>
#include <string>
#include <sstream>
//global variables
//TODO make players start from 0
int firstPlayer;
int deck[52];
int nextCard=0;
PokerTable aPokerTable(9,9,1,20,30,false,false,false);
PokerPlayer players[9]; //however many players
ofstream gameLog;
/*
void setTable()
{
aPokerTable.setNumPlayers(9);
aPokerTable.setNumPlaying(9);
aPokerTable.setDealerPos(1);
aPokerTable.setBigBlind(20);
aPokerTable.setPotSize(30);
aPokerTable.setBetSize(20);
aPokerTable.setFlop(false);
aPokerTable.setTurn(false);
aPokerTable.setRiver(false);
}
*/
string convertInt(int number) //convert to string
{
stringstream ss;//create a stringstream
ss << number;//add number to the stream
return ss.str();//return a string with the contents of the stream
}
void createPlayers()
{
// aPokerTable.setNumPlayers(9);
for(int x=0;x<=(aPokerTable.getNumPlayers()-1);x++)
{
players[x] = *(new PokerPlayer(1000,(aPokerTable.getDealerPos())+1,false,0,1));//1000 chips, position i+1, not folded
}
}
void playRound()
{
int action;
for(int playerTurn = firstPlayer; playerTurn <= aPokerTable.getNumPlayers()+firstPlayer; playerTurn++)
{
if(players[playerTurn].getFold() == false)
{
if(aPokerTable.getNumPlaying() == 1)
{
players[playerTurn].setChipStack(players[playerTurn].getChipStack() + aPokerTable.getPotSize()); //player wins pot
}
else //there is more than one person playing
{
action = players[playerTurn].action(); //0 is check/fold, value is call/bet/raise,
if(action > aPokerTable.getBetSize())
{
aPokerTable.setBetSize(action);
aPokerTable.setPotSize(aPokerTable.getPotSize() + action);
playerTurn = playerTurn - aPokerTable.getNumPlayers();
}
else if (action == aPokerTable.getBetSize()) //call
{
aPokerTable.setPotSize(aPokerTable.getPotSize() + action);
}
else //action < aPokerTable.betSize
{
players[playerTurn].setFold(true);
aPokerTable.setNumPlaying(aPokerTable.getNumPlaying()-1); //removes player from playing tally
}
}
}
}
}
void randomDeck()
{
int random_integer;
int tempCard;
//srand((unsigned)time(0));
for(int j=0;j<=51;j++)
{
deck[j] = j;
}
for(int i=51; i>=1; i--)
{
random_integer = rand()%(i); //a random number between 0 and i
tempCard = deck[i];
deck[i] = deck[random_integer]; //put the random card from unshuffled deck into slot i of the deck
deck[random_integer] = tempCard; //put whatever was at slot i into the random slot
}
}
void dealCards()
{
for(int j=1;j<=aPokerTable.getNumPlayers();j++)
{
players[j].setCard1(deck[nextCard]);
nextCard++;
players[j].setCard2(deck[nextCard]);
nextCard++;
}
}
void playPreFlop()
{
aPokerTable.setBetSize(aPokerTable.getBigBlind());
aPokerTable.setFlop(false); //it is before the flop
aPokerTable.setTurn(false);
aPokerTable.setRiver(false);
randomDeck(); //shuffle cards
dealCards();
firstPlayer = (aPokerTable.getDealerPos() + 3)%(aPokerTable.getNumPlayers()); // first player is left of blinds between 0 and numplayers
playRound();
}
void playFlop()
{
aPokerTable.setFlop(true);
firstPlayer = (aPokerTable.getDealerPos())%aPokerTable.getNumPlayers(); // first player is left of dealer between 0 and numplayers
aPokerTable.setBetSize(0);
playRound();
}
void playTurn()
{
aPokerTable.setTurn(true);
firstPlayer = (aPokerTable.getDealerPos())%aPokerTable.getNumPlayers(); // first player is left of dealer between 0 and numplayers
aPokerTable.setBetSize(0);
playRound();
}
void playRiver()
{
aPokerTable.setRiver(true);
firstPlayer = (aPokerTable.getDealerPos())%(aPokerTable.getNumPlayers()); // first player is left of dealer between 0 and numplayers
aPokerTable.setBetSize(0);
playRound();
if(aPokerTable.getNumPlaying() >=2)
{
//showDown();
}
}
/*
void showDown()
{
}
*/
This is pokerPlayer.h
using namespace std;
class PokerPlayer
{
private:
int chipStack,position;
bool fold;
int card1,card2;
public:
//constructors
PokerPlayer();
PokerPlayer(int,int,bool,int,int);
//getters
int getChipStack() {return chipStack;}
int getPosition() {return position;}
int getCard1(){return card1;}
int getCard2(){return card2;}
bool getFold(){return fold;}
//setters
void setChipStack(int inChips){chipStack = inChips;}
void setPosition(int inPos){position = inPos;}
void setCard1(int inCard1){card1 = inCard1;}
void setCard2(int inCard2){card2 = inCard2;}
void setFold(bool inFold){fold = inFold;}
int action();
};
PokerPlayer::PokerPlayer()
{
chipStack = 1000;
position = 0;
fold=false;
card1 = 0;
card2 = 1;
}
PokerPlayer::PokerPlayer(int inChipStack,int inPos, bool inFold, int inCard1, int inCard2)
{
chipStack = inChipStack;
position = inPos;
fold = inFold;
card1 = inCard1;
card2 = inCard2;
}
int PokerPlayer::action()
{
return 0;
}
aPokerTable { numPlayers=2990892 numPlaying=9 dealerPos=9 ...}
Note that dealerPos got assigned the value 9, that's wrong as well. If you look closely, you'll see that everything is shifted by 4 bytes.
Two possible reasons. The debugger could have picked the wrong address for aPokerTable, the actual address minus 4. That's unlikely. Or there's a mismatch between the definition of the PokerTable class as seen by pokertable.cpp and the other .cpp files that #include the pokertable.h include file. Where pokertable.cpp saw an extra member before the numPlayers member. Maybe you edited the header and deleted that member but ended up not recompiling pokertable.cpp for some mysterious reason. Build + Rebuild to fix. Do panic a bit if this actually works.
It's because in C++ before the constructor is called, variable uses the value that it already contains in its memory location that is a "random" value
I cannot reconstruct it because i dont have the full code. However, a random value near 4 million sounds like a pointer. When you store or retrieve a member variable maybe you did not de-reference the pointer. Please post the rest of the code so we can check if that's the case.
players[x] = *(new PokerPlayer(...));
That is a memory leak. What you probably want is:
players[x] = PokerPlayer(1000,(aPokerTable.getDealerPos())+1,false,0,1);