Program Has Unexpectedly Finished - c++

My execution program won't work properly, for whatever reason.
#include <QtCore/QCoreApplication>
#include <tinyxml/tinyxml.h>
#include "classowner.h"
#include "character.h"
int main(int argc, char *argv[])
{
Character * holland = new Character("Holland", HUMAN, MALE);
delete &holland;
std::cout << "Hello, World!" << std::endl;
return 0;
}
All my output states is that the program won't execute properly. The output doesn't display, however when I don't allocate the object, it will. Obviously, it's the object. What am I doing wrong?
Update
It appears the problem may be something more than deleting and allocating memory. Thus, I'm going to post the implementation behind the Character class.
Header:
#include <iostream>
#ifndef CHARACTER_H
#define CHARACTER_H
enum Race {HUMAN, DARK_ELF};
enum Gender {MALE, FEMALE};
class Character
{
public:
Character();
Character(std::string char_name, Race char_race, Gender char_gender);
~Character();
int get_id() { return this->char_id; }
std::string get_name() { return this->name; }
Race get_race() { return this->race; }
Gender get_gender() { return this->gender; }
private:
int char_id;
static int * char_count;
std::string name;
Race race;
Gender gender;
};
#endif // CHARACTER_H
//Source:
#include "character.h"
#include <iostream>
int * Character::char_count = 0;
Character::Character()
{
this->char_id = *char_count;
char_count++;
}
Character::Character(std::string char_name, Race char_race, Gender char_gender)
{
this->char_id = *char_count;
char_count++;
this->name = char_name;
this->race = char_race;
this->gender = char_gender;
}
Character::~Character()
{
}

delete &holland;
should be
delete holland;
Less profanity would be appreciated.
On the other hand, posting a short example that succinctly illustrates the problem is very much appreciated.

First of all, you try to dereference a null pointer:
int * Character::char_count = 0;
Both constructors of class Character do this
this->char_id = *char_count;
and that's an attempt to dereference a null pointer. That code makes no sense to me, I guess you could just use int instead of pointer:
int Character::char_count = 0;
//then
this->char_id = char_count;
Also here:
Character * holland = new Character("Holland", HUMAN, MALE);
you create an object of type class Character. You have to delete that object through a pointer to class Character - the pointer should have type Character*. Instead you try to use delete on a pointer of type Character**and that leads to undefined behavior.
So instead of
delete &holland;
you have to use
delete holland;

Related

How can I access and modify the attributes of a class stored in a vector if I delete the "original" object?

I'm making an application that allows to quote clothes in a store.
In my Store class, I have defined a vector of class Clothes, where I must store the different types of clothing to sell (derived clothing classes such as Shirt and Pants).
My problem arises in that, it does not allow me to access the objects stored in the vector if I have deleted the "original" object. From what I understood, std::vector performed a copy constructor and had its own space to store data, so it is not clear to me why I am not being able to access and modify the attributes of the objects that are already inside the vector. Depending on the different solutions that I tried, the compiler showed me different read or write access errors.
PS: If I don't delete the original object (after having entered the vector), the code works fine for me, and allows me to remove it from the vector and add another object, which I CAN DELETE after entering it into the vector.
Store.h
#pragma once
#ifndef STORE_H
#define STORE_H
#include <string>
#include <vector>
class Clothes;
class Shirt;
class Pants;
class Store
{
private:
std::string storeName;
std::string address;
std::vector<Clothes*> clothesList;
Shirt* _shirt;
Pants* _pants;
public:
Store();
~Store();
void setClothesPreferences(int clothesType, int alternative1, int alternative2, int quality);
};
#endif // !STORE_H
Store.cpp
#include "Store.h"
#include "Clothes.h"
#include "Shirt.h"
#include "Pants.h"
#include <iostream>
Store::Store()
{
std::cout << "Please, introduce your store name: ";
std::getline(std::cin, storeName);
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::cout << "Store address: ";
std::getline(std::cin, address);
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
_shirt = new Shirt();
_pants = new Pants();
clothesList.push_back(_shirt);
clothesList.push_back(_pants);
// If I use delete _shirt here then I would get an error in setClothesPreferences()
}
Store::~Store()
{
std::cout << "Store closed" << std::endl;
}
void Store::setClothesPreferences(int clothesType, int alternative1, int alternative2, int quality)
{
if (clothesType == 1)
{
Shirt* _shirt2 = dynamic_cast<Shirt*>(clothesList.front()); // Type-casting from Clothes (base class) to Shirt again (derived class)
clothesList.erase(clothesList.begin());
// SHIRT SPECIFICATIONS FOR FURTHER QUOTE
if (alternative1 == 1)
_shirt2->shortSleeve = true;
else
_shirt2->shortSleeve = false; // longSleeve
if (alternative2 == 1)
_shirt2->mandarinCollar = true;
else
_shirt2->mandarinCollar = false; // regularCollar
if (quality == 1)
_shirt2->quality; // Standard
else
_shirt2->quality; // Premium
clothesList.insert(clothesList.begin(), _shirt2);
}
}
Clothes.h
#pragma once
#ifndef CLOTHES_H
#define CLOTHES_H
#include <string>
class Clothes
{
public:
std::string derivedName;
std::string quality[2];
double unitPrice;
int stockAmount;
Clothes();
virtual ~Clothes();
};
#endif // !CLOTHES_H
Clothes.cpp
#include "Clothes.h"
Clothes::Clothes()
{
derivedName = "Base default";
quality[0] = "Standard";
quality[1] = "Premium";
unitPrice = NULL;
}
Clothes::~Clothes()
{
}
Shirt.h
#pragma once
#ifndef SHIRT_H
#define SHIRT_H
#include "Clothes.h"
class Shirt : public Clothes
{
public:
bool shortSleeve;
bool mandarinCollar;
Shirt();
~Shirt() override;
};
#endif // !SHIRT_H
Shirt.cpp
#include "Shirt.h"
Shirt::Shirt()
{
derivedName = "Shirt";
stockAmount = 2000;
}
Shirt::~Shirt()
{
}
My idea is actually to create a local object of class Shirt, insert it into the vector, and when the Clothes function or constructor is finished, it would be deleted, but I would still have access and modify its data from what is stored in the vector.

C++ Object doesn't save value

Objects I created for the Player class does not change the private variable even tho it does in the function that changes it. There maybe some reference problems with the objects being used in the main() function but I can't figure out where or why.
Specifically the loop at the end of the main file prints the games won by the players in the vector Players but all the scores return 0. While when the player object.matchWon() function correctly parse and print the score and shows the change made to the private variable.
I suspect there are problems with the usage of getPlayer() function in the main code.
Thanks in advance!!
Player.cpp:
#include "Player.h"
#include <stdlib.h>
#include <iostream>
using namespace std;
//constructor
Player::Player(string first, string last) {
Player::first = first;
Player::last = last;
gWins = 0;
gLoss = 0;
mWins = 10;
mLoss = 2;
}
//setters
void Player::addLoss(int increment) {
this->gLoss+=increment;
}
void Player::addWins(int increment) {
this->gWins+=increment;
}
void Player::matchWon(vector<string> scores) {
for (int i = 5;i<scores.size()-1;i++){
cout<<(int)scores[i][0]-'0'<<"-";
cout<<(int)scores[i][2]-'0'<<endl;
gWins+=scores[i][0]-'0'; //add games won
cout<<gWins<<endl;
gLoss+=(int)scores[i][2]-'0'; //add games lost
}
this->mWins++;
}
void Player::matchLost(vector<string> scores) {
this->mLoss++;
}
double Player::winPercentage() {
return (double)mWins / mLoss;
}
//accessors
string Player::getFirstname() {
return this->first;
}
string Player::getLastname() {
return this->last;
}
int Player::getGameswon() {
//cout<<gWins;
return this->gWins;
}
main.cpp:
#include <iostream>
#include "player.h"
#include <fstream>
#include <vector>
#include <sstream>
using namespace std;
vector<string> split(const string &s) {
vector<string> elems;
istringstream iss(s);
do
{
string sub;
iss >> sub;
elems.push_back(sub);
//cout << "Substring: " << sub << endl;
} while (iss);
return elems;
}
Player &getPlayer(vector<Player> &players, const string &first, const string &last){
for (int i=0;i<players.size();i++){
if (players[i].getFirstname()==first&&players[i].getLastname()==last){
return players[i];
}
}
players.push_back(Player(first,last));
return (players[players.size()-1]);
}
int main(int argc, char *argv[]) {
ifstream file(argv[1]);
ofstream ofile(argv[2]);
if (!file.is_open()){
cerr <<"Could not open file\n";
return 0;
}
string line;
vector<Player> players;
while (getline(file,line).good()){
vector<string> lineParsed = split(line);
vector<string> matchData = split(line);
Player p1 = getPlayer(players,lineParsed[0],lineParsed[1]);
Player p2 = getPlayer(players,lineParsed[3],lineParsed[4]);
p1.matchWon(lineParsed);
cout<<p1.getFirstname()<<"!"<<p1.getGameswon()<<endl;
}
for (int i=0;i<players.size();i++){
//cout<<players.size();
cout<<players[i].getFirstname()<<":"<<players[i].getGameswon()<<endl;
}
return 0;
}
You're copying your players:
Player p1 = getPlayer(players,lineParsed[0],lineParsed[1]);
Player p2 = getPlayer(players,lineParsed[3],lineParsed[4]);
so when you p1.matchWon(), it happens to the local Player object, not the one in the vector.
Although the return type of getplayer() is Player&, that doesn't matter if you're assigning it to a non-reference variable. If you want to be modifying the Player instances in the vector, you should have
Player& p1 = getPlayer(players,lineParsed[0],lineParsed[1]);
Player& p2 = getPlayer(players,lineParsed[3],lineParsed[4]);
By the way, getPlayer() is unsafe. The vector might resize itself when you push_back to it, invalidating references. You may want to store a vector of pointers instead (or just make sure through e.g. resize() that the vector definitely has room for all the players you want to push to it).
It would help if you included the class definition. There seems to be something strange going on:
Player::first = first;
Player::last = last;
Are these static fields? If they are, the issue is that you only store the first and last (names?) of the last player you create.

c++ method parameters giving unexpected output

Main class code:
#include <iostream>
#include "Chair.h"
using namespace std;
int main()
{
cout << "Hello world!" << endl;
Chair c1;
c1.chairType("Olivia",4,32,true); // not working
Chair c2;
c1.chairType("Stephano",8,8,false);
return 0;
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Header class code:
#ifndef CHAIR_H_INCLUDED
#define CHAIR_H_INCLUDED
#include <iostream>
using namespace std;
class Chair
{
private:
int legCount;
int height;
bool cushioned;
string name;
public:
void chairType(string newName, int newLegCount, int newHeight, bool cush);
};
#endif // CHAIR_H_INCLUDED
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Chair.cpp class:
#include <iostream>
#include "Chair.h"
using namespace std;
void Chair::chairType(string newName, int newLegCount, int newHeight, bool cush)
{
name=newName;
legCount=newLegCount;
newHeight=newHeight;
cushioned=cush;
cout<<"I'm a chair, the following are my specs: "<<endl;
cout<<"Model: "<<name<<endl;
cout<<"Num of Legs: "<<legCount<<endl;
cout<<"Height: "<<height<<endl;
cout<<"Cushioned? : "<<cush<<endl;
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Output for the four variables fed into the method is as expected, apart from the third variable (second int) which is printing as being 2752192 regardless of what I feed to it, and for both objects c1 and c2.
I'm new to C++. I've been practising some object class questions trying to familiarise myself with the syntax. I vaguely understand pointers can cause reference addresses to print on occasion. However, this 7 digit number doesn't appear to be in address format. I've done some searches and can't see a similar question. If there is one, I would appreciate direction to it. I don't wish to break the terms of posting here on the site. Thank you in advance for your assistance.
newHeight=newHeight;
should be replaced with
height=newHeight;
but better you should initialize object in constructor, rather than separate method:
class Chair
{
private:
int legCount;
int height;
bool cushioned;
string name;
public:
Chair( const string &newName, int newLegCount, int newHeight, bool cush) :
legCount( newLegCount ),
height( newHeight ),
cushioned( cush ),
name( newName )
{
}
...
};
int main()
{
cout << "Hello world!" << endl;
Chair c1("Olivia",4,32,true); // works now
Chair c2("Stephano",8,8,false);
return 0;
}
this way you cannot have instance of your class uninitialized and your mistake also would be detected by compiler.
Here is the mistake in your implementation Chair.cpp:
newHeight=newHeight;
This is the correct:
height = newHeight;
The long number you get is the uninitialized value of member variable height in your Chair object.

Access violation writing location when using pointers

I'm trying to write a program that allows a user to input data into a text file to organize class assignments. The user can display the list of assignments, enter an assignment into the file, and search for specific course work that is due. I am having a problem where I get an access violation writing location error and I'm not entirely sure how to fix it. I have looked at previous discussions that are posted but can't quite figure out where I am going wrong in my code.
This is taskList.cpp.
The header file taskList.h is posted after it.
I'm using VS2013.
When I debug the error is posted at line 55 in the taskList.cpp file below
list = new Task[capacity];
#include "taskList.h"
#include "mytools.h"
TaskList::TaskList()
{
capacity = CAP;
list = new Task[capacity];
size = 0;
}
TaskList::TaskList(char filename[])
{
capacity = CAP;
list = new Task[capacity];
size = 0;
//load from file.
ifstream inData;
Task aTask;
char tempName[MAXCHAR];
char tempDescription[MAXCHAR];
char tempDate[MAXCHAR];
inData.open("task.txt");
if (!inData){
cout << "cannot open file";
exit(0);
}
inData.getline(tempName, MAXCHAR, ';');
while (!inData.eof())
{
inData.getline(tempDescription, MAXCHAR, '\n');
inData.getline(tempDate, MAXCHAR, '\n');
aTask.setName(tempName);
aTask.setDescription(tempDescription);
aTask.setDate(tempDate);
addTask(aTask);
inData.getline(tempName, MAXCHAR, ';');
}
inData.close();
;
TaskList::~TaskList()
{
if (list)
{
delete [] list;
list = NULL;
}
}
//Adds a video item to the list
void TaskList::addTask(Task aTask)
{
list[size++] = aTask;
}
//displays the list of videos
void TaskList::showList()
{
int i = 0;
for (i = 0; i < size; i++)
{
list[i].printTask();
}
}
void TaskList::searchList()
{
char searchName[MAXCHAR];
char tempName[MAXCHAR];
int i;
bool found = false;
cout << "Enter the name of the course to search for: ";
cin.getline(searchName, MAXCHAR);
for (i = 0; i < size; i++)
{
list[i].getName(tempName);
if (strstr(searchName, tempName) != NULL)
{
list[i].printTask();
found = true;
}
}
if (found == false)
cout << "No search results." << endl;
}
void TaskList::writeData()
{
ofstream outData;
outData.open("task.txt");
if (!outData)
{
cout << "cannot open file";
exit(0);
}
for (int i = 0; i < size; i++)
list[i].printToFile(outData);
outData.close();
}
//expand array function
void TaskList::expand()
{
char tempName[MAXCHAR];
char tempDescription[MAXCHAR];
char tempDate[MAXCHAR];
capacity += GROWTH;
Task *temp = new Task[capacity];
//copy from old array to new array
for (int i = 0; i < size; i++)
{
list[i].getName(tempName);
list[i].getDescription(tempDescription);
list[i].getDate(tempDate);
temp[i].setName(tempName);
temp[i].setDescription(tempDescription);
temp[i].setDate(tempDate);
}
//delete old array
delete [] list;
list = NULL;
//point ptr to temp
list = temp;
//set temp to NULL
temp = NULL;
}
The header file (taskList.h)
#include <iostream>
#include <fstream>
using namespace std;
const int CAP = 2;
const int GROWTH = 2;
//define class VideoList for array of Videos and its size.
class TaskList
{
private:
Task *list;
int size;
int capacity;
void expand();
public:
//constructors
TaskList();
TaskList(char filename[]);
//destructor
~TaskList();
//database functions
void addTask(Task aTask);
void showList();
void searchList();
void writeData();
};
#endif
Just to be sure that everything is made clear because there are 3 header files, 4 source files, and a text file, I am include the task.h header file and task.cpp source file.
Here is task.h:
#ifndef TASK_H
#define TASK_H
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string.h>
using namespace std;
const int MAXCHAR = 101;
class Task
{
private:
char *name;
char *description;
char *date;
public:
//defult constructor
Task();
//constructor with parameters
Task(char newName[], char newDescription[], char newDate[]);
//copy constructor
Task(const Task &otherTask);
//Accessor funct
void getName(char returnName[]);
void getDescription(char returnDescription[]);
void getDate(char returnDate[]);
//mutator function
void setName(char newName[]);
void setDescription(char newDescription[]);
void setDate(char newDate[]);
//print function to print a video
void printTask();
void printToFile(ofstream &outFile);
const Task& operator= (const Task& anItem);
};
#endif
Here is the task.cpp file, not sure if this is necessary but I am adding it for clarity:
#include "task.h"
#include <iostream>
using namespace std;
//defult constructor
Task::Task()
{
strcpy(name, "no course name");
strcpy(description, "no task description");
strcpy(date, "no due date");
}
//constructor with parameters
Task::Task(char newName[], char newDescription[], char newDate[])
{
name = new char[strlen(newName) + 1];
description = new char[strlen(newDescription) + 1];
date = new char[strlen(newDate) + 1];
strcpy(name, newName);
strcpy(description, newDescription);
strcpy(date, newDate);
}
//copy constructor
Task::Task(const Task &otherTask)
{
//allocate memory and then copy name
this->name = new char[strlen(otherTask.name) + 1];
strcpy(name, otherTask.name);
//allocate memory and then copy description
this->description = new char[strlen(otherTask.description) + 1];
strcpy(description, otherTask.description);
//allocate memory and then copy date
this->date = new char[strlen(otherTask.date) + 1];
strcpy(date, otherTask.date);
}
//Accessor functions
void Task::getName(char returnName[])
{
strcpy(returnName, name);
}
void Task::getDescription(char returnDescription[])
{
strcpy(returnDescription, description);
}
void Task::getDate(char returnDate[])
{
strcpy(returnDate, date);
}
//mutator functions
void Task::setName(char newName[])
{
strcpy(name, newName);
}
void Task::setDescription(char newDescription[])
{
strcpy(description, newDescription);
}
void Task::setDate(char newDate[])
{
strcpy(date, newDate);
}
//prints a video item
void Task::printTask()
{
cout << name << ';' << description << ';' << date << endl;
}
void Task::printToFile(ofstream &outFile)
{
outFile << name << ';' << description << ';' << date << endl;
}
//assignment operator overloaded
const Task& Task::operator= (const Task& aTask)
{
strcpy(this->name, aTask.name);
this->description = aTask.description;
strcpy(this->description, aTask.description);
this->date = aTask.date;
strcpy(this->date, aTask.date);
return *this;
}
Here is the problem:
char *name;
// ...
strcpy(name, "no course name");
The first line creates a pointer which currently does not point anywhere. Then you tell strcpy to copy that string to where the pointer is pointing, so it writes the string to "nowhere" (in practice: a semi-random memory location). This causes your access violation.
To fix this, replace the code with:
std::string name;
// ...
name = "no course name";
Do the same for description and date. Note that this means you don't need a copy-constructor or copy-assignment operator or destructor; because the default ones behave correctly.
Of course you will need to change your accssor functions (but they were badly designed anyway since the caller cannot prevent a buffer overflow):
std::string getName() const { return name; }
Also, change Task *list; to std::vector<Task> list; and stop using new and delete. The vector correctly manages memory for you.
It is simplest and easiest to do this task without using pointers or manual memory management or C-library functions such as strcpy. You'll halve your code size (at least) and it will be much less prone to error.
You may need #include <string> and #include <vector>.
Since the erroe happens at allocation if an array (list = new Task[capacity]) i guess your problem is in default constructor of Task class. try playing with this constructor a liitle , i suggest allocating yor char arrays (names , descriptions and data) befor filling them.
somecode like name = new Char[14]; (and of course same for the other two)
You have failed to follow the rule-of-five or the rule-of-zero.
The correct thing (rule-of-zero) would be to implement TaskList in terms of std::vector<Task>.
Seeing as your assignment demands that you use a "dynamic array", perhaps they don't want you to use std::vector. This means that you are stuck with manual memory management. This means that you need to correctly implement or remove the following functions:
//You have these
TaskList::TaskList();
TaskList::TaskList(char filename[]);
TaskList::~TaskList();
//You are missing these, this is your problem:
TaskList::TaskList(TaskList const &o); //Copy constructor
TaskList &TaskList::operator=(TaskList const &o); //Copy assignment
TaskList::TaskList(TaskList &&o); //Move constructor
TaskList &TaskList::operator=(TaskList &&o); //Move assignment
If you do not explicitly supply these functions, the compiler may automatically generate them, and the compiler-generated versions will be incorrect (for the situation where you are manually managing resources within TaskList), as they will do member-wise moves or copies, rather than copying or moving the underlying resources. When you then use these incorrect compiler-generated versions, your code will have strange behaviour.
For Task, you shouldn't be managing multiple resources at once. Use std::string, or otherwise write your own string class, and then use it to manage the string members of Task. If you do not, your code is almost guaranteed to be incorrect (due to a lack of exception safety).

C++ Implementing a copy constructor

I am writing some code to implement a deep copy of an object.
Here is my code:
//---------------------------------------------------------------------------
#pragma hdrstop
#include <tchar.h>
#include <string>
#include <iostream>
#include <sstream>
#include <conio.h>
using namespace std;
//---------------------------------------------------------------------------
class Wheel
{
public:
Wheel() : pressure(32)
{
ptrSize = new int(30);
}
Wheel(int s, int p) : pressure(p)
{
ptrSize = new int(s);
}
~Wheel()
{
delete ptrSize;
}
void pump(int amount)
{
pressure += amount;
}
int getSize()
{
return *ptrSize;
}
int getPressure()
{
return pressure;
}
private:
int *ptrSize;
int pressure;
};
class RacingCar
{
public:
RacingCar()
{
speed = 0;
*carWheels = new Wheel[4];
}
RacingCar(int s)
{
speed = s;
}
RacingCar(RacingCar &oldObject)
{
for ( int i = 0; i < sizeof(carWheels)/sizeof(carWheels[0]); ++i)
{
Wheel oldObjectWheel = oldObject.getWheel(i);
carWheels[i]=new Wheel(oldObjectWheel.getSize(),oldObjectWheel.getPressure());
}
}
void Accelerate()
{
speed = speed + 10;
}
Wheel getWheel(int id)
{
return *carWheels[id];
}
void printDetails()
{
cout << carWheels[0];
cout << carWheels[1];
cout << carWheels[2];
cout << carWheels[3];
}
private:
int speed;
Wheel *carWheels[4];
};
#pragma argsused
int _tmain(int argc, _TCHAR* argv[])
{
RacingCar testCar;
testCar.printDetails();
RacingCar newCar = testCar;
newCar.printDetails();
getch();
return 0;
}
//---------------------------------------------------------------------------
For some reason, my C++ builder crashes after compiling this code. Is there anything above that is not correct that would cause this to crash. There is no compile error, the program just crashes.
The problem is:
Wheel *carWheels[4];
and
*carWheels = new Wheel[4];
this only allocates 4 Wheels for carWheels[0]. Along with
return *carWheels[id];
If id is not 0, this will lead to undefined behavior because, as previously stated, only the first element is a valid pointer.
Besides this, the code is horrible. Avoid raw pointers. There are much better alternatives in C++. Use std::vector or std::array where you'd use a C-array, and smart pointers where you'd use raw ones.
Generally in my experience, if my compiler/tool crashes, I'm probably doing something so wrong that it never even occurred to the compiler writers to check for it.
The best way to track down such things is to comment out code until it works again, then slowly bring stuff back in until you find the offending part.
As a design note, I'd say that if it were me, I'd implement a copy constructor for Wheel as well, rather than having to write a complex deep copy constructor for classes like RacingCar that use it.