below i wrote a simple example to demonstrate the problem I experience. After executing the code, I get a cygwin exception 7200. I have looked around and tried a few things but to no resolve. Could somebody explain why do I get it, and how could I fix it? Appreciate your time, and many thanks in advance!
Code
#include <string>
#include <vector>
// string
using std::string;
// vector
using std::vector;
class Person{
private:
string name;
int age;
public:
Person(string& name, int& age);
};
Person::Person(string& name, int& age): name(name), age(age){}
int main(){
vector<Person> people;
string* names = new string[3];
names[0] = "bob";
names[1] = "alice";
names[2] = "hank";
int* ages = new int[3];
ages[0] = 10;
ages[1] = 20;
ages[2] = 30;
for(unsigned int i = 0; i < 3; ++i){
Person person(names[i], ages[i]);
people.push_back(person);
}
delete names;
delete ages;
return 0;
}
Error
0 [main] a 7200 cygwin_exception::open_stackdumpfile: Dumping stack
trace to a.exe.stackdump
P.S - I am relatively new to C++.
You need to delete arrays with delete[] rather than delete.
delete[] names;
delete[] ages;
Related
I am trying to create an array of objects in C++. As C++ Supports native objects like int, float, and creating their array is not a problem.
But when I create a class and create an array of objects of that class, it's not working.
Here is my code:
#include <iostream>
#include <string.h>
using namespace std;
class Employee
{
string name;
int age;
int salary;
public:
Employee(int agex, string namex, int salaryx)
{
name = namex;
age = agex;
salary = salaryx;
}
int getSalary()
{
return salary;
}
int getAge()
{
return age;
}
string getName()
{
return name;
}
};
int main(void)
{
Employee **mycompany = {};
//Create a new Object
mycompany[0] = new Employee(10, "Mayukh", 1000);
string name = mycompany[0]->getName();
cout << name << "\n";
return 0;
}
There is no compilation error, but when I'm running the Program, it is crashing. I don't know exactly what is happening here.
Please Help.
Here are some more details:
OS: 64bit Windows 8.1 on Intel x64 (i3) Architecture of Compiler: MinGW64 G++ Compiler
The advice here, as always, is to use some STL container, like an std::vector.
That said you're probably going to need a default Employee constructor (unless you always initialize all the elements of the container with the constructor you already have, which is unlikely what you'll do, if you are to manually allocate memory, but more likely if you use a std::vector).
//...
Employee() = default; // or Employee(){}
Employee(int agex, string namex, int salaryx)
{
name = namex;
age = agex;
salary = salaryx;
}
//...
If you really, absolutely, must do it by manual memory allocation, it would look roughly like this:
// Employee array with 5 employees, with the first two initialized with your constructor
Employee *mycompany = new Employee[5] {{10, "Mayukh1", 1000}, {20, "Mayukh2", 2000}};
//adding an employee
mycompany[2] = {30, "Mayukh3", 3000};
// it still has space for 2 more
Don't forget to delete the memory afterwards:
delete [] mycompany;
Live demo
this is how you would do that:
#include <iostream>
#include <string.h>
using namespace std;
class Employee
{
string name;
int age;
int salary;
public:
Employee(int agex, string namex, int salaryx)
{
name = namex;
age = agex;
salary = salaryx;
}
int getSalary()
{
return salary;
}
int getAge()
{
return age;
}
string getName()
{
return name;
}
};
int main(void)
{
//Create an Array length of 10
// in c++ its static you have to give the length of the array while declaring
Employee mycompany [10];
//Create a new Object
mycompany[0] = new Employee(10, "Mayukh", 1000);
string name = mycompany[0]->getName();
cout << name << "\n";
return 0;
}
Consider the stretch of code below:
#include <iostream>
using std::cout;
using std::string;
using std::endl;
class SuperPower{
private:
string name;
int category;
public:
string getName(){return name;}
int getCategory(){return category;}
SuperPower(string name, int category){
this->name = name;
this->category = category;
}
};
class Person{
private:
string name, nameRealLife;
SuperPower **powers;
SuperPower *powers2;
int nPowers;
protected:
Person(string name, string nameRealLife){
this->name = name;
this->nameRealLife = nameRealLife;
powers = new SuperPower*[4];
powers2 = new SuperPower[4]("",0);
nPowers = 0;
}
public:
~Person(){
delete []powers;
}
Person(const Person& p){
name = p.name;
nameRealLife = nameRealLife;
powers = new SuperPower*[4];
nPowers = p.nPowers;
for (int i=0;i<nPowers;i++)
powers[i] = p.powers[i];
}
string getName(){
return name;
}
bool addSuperPower(SuperPower &sp){
if (nPowers>=4)
return false;
powers[nPowers++] = &sp;
return true;
}
virtual double getTotalPower(){
double totalPower = 0;
for (int i=0;i<nPowers;i++){
totalPower += powers[i]->getCategory();
}
return totalPower;
}
};
...
My professor asked to solve a Objected Oriented Problem and I am struggling with the compiler to finish it because of this line:
powers2 = new SuperPower[4]("",0);
Trying to compile the code results in error: parenthesized initializer in array new [-fpermissive]
powers2 = new SuperPower4;
Why is it wrong? Isn't it just definning the constructor's parameters? Why does it happen? How should I fix it?
Do not use raw pointers. Use std::vector. It makes the life easier.
std::vector<SuperPower> powers2; // declaration
...
powers2(4, SuperPower("",0)), // in constructors's initialisation list
You can make it work by using: powers2 = new SuperPower[4]{{"", 0},{"", 0},{"", 0},{"", 0}}; instead of powers2 = new SuperPower[4]("",0); but don't do this, instead I insist you on using std::vector like this:
std::vector<Superpower> powers2;
and then in ctor:
powers2(4, Superpower("", 0));
I learned C++ yesterday an I'm trying to solve USACO training problems.
http://train.usaco.org/usacoprob2?a=iKSzALidh4Q&S=gift1
For this one, I have created a vector of People pointers. However, after some troubleshooting, I discovered that when I try to do something like
Person bob = *(people.at(i));
or
people.at(i) -> setbalance(giveself); // giveself is an int
The program is not responding and:
Process terminated with status -1073741819 (0 minute(s), 3 second(s).
I'm also new to this forum.
Here is my code:
include statments
using namespace std;
class Person
{
private:
int balance;
int origbalance;
string name;
public:
int getbalance() {return balance;}
string getname() {return name;}
void setbalance(int b){balance +=b;}
void setorigbalance(int o) {origbalance = o;}
int getorigbalance() {return origbalance;}
void giveTo(int num, Person* y) {y->setbalance(num);}
~Person();
Person(string n);
};
Person::Person(string n)
{
name = n;
}
Person::~Person()
{
}
int main()
{
ofstream fout ("gift1.out");
ifstream fin ("gift1.in");
int NP;
fin>>NP;
cout<<NP<<endl;
vector<Person*> people(NP);
cout<<"Created vector\n"<<endl;
for(int i = 0; i<NP; i++)
{
string nam;
fin>>nam;
Person* p = new Person(nam);
people.push_back(p);
cout<<nam<<endl;
}
cout<<"\nFilled vector, size = "<<people.size()<<endl;
for(int i = 0; i<NP; i++)
{
string temp;
fin>>temp;
cout<<"\nNow receiving "<<temp<<endl;
int togive, numgiving;
fin>>togive>>numgiving;
cout<<"\n"<<temp<<" is dividing "<<togive<<" among "<<numgiving<<" people"<<endl;
Person bob = *(people.at(i));
cout<<"hi bob"<<endl;
//(*people.at(i)).setorigbalance(togive);
cout<<"Original balance set"<<endl;
int giveeach = togive/numgiving;
cout<<"or "<<giveeach<<" to each person"<<endl;
int giveself = togive%numgiving;
cout<<"and "<<giveself<<" to himself :/"<<endl;
people.at(i) -> setbalance(giveself);
for(int j=0; j<numgiving; j++)
{
string nametogiveto;
fin>> nametogiveto;
cout<<nametogiveto<<endl;
for(int k=0; k<NP; k++)
{
string namy = people.at(k)->getname();
if(namy==nametogiveto)
{
cout<<"\nHere you go "<<namy<<" have "<<giveeach<<endl;
people.at(k)->setbalance(giveeach);
people.at(i)->setbalance(-giveeach);
break;
}
}
}
}
for(int i=0; i<NP; i++)
{
cout<<people.at(i)->getname()<<endl;;
cout<<people.at(i)->getorigbalance() - people.at(i)->getbalance()<<endl;
cout<<endl;
fout<<people.at(i)->getname();
fout<<people.at(i)->getorigbalance() - people.at(i)->getbalance()<<endl;
}
return 0;
}
You're running into undefined behavior due to dereferencing null pointers.
vector<Person*> people(NP);
This line creates the vector with NP null pointers. You later add on your actual pointers but only ever access the first NP elements which are the null pointers.
That said you don't even need pointers here and I'd recommend getting rid of them. In fact you have memory leaks due to allocating pointers with new but never calling delete on them. In my experience it's typical for people just starting out with C++ to overuse pointers, so think about ways to avoid them first.
Change
vector<Person*> people(NP);
to
vector<Person> people;
and fill it using:
for(int i = 0; i<NP; i++)
{
string nam;
fin>>nam;
Person p(nam); // no more need for pointer or new here
people.push_back(p);
cout<<nam<<endl;
}
later when accessing it you don't need any dereferencing anymore either. That means you can get rid of all the * for example:
Person bob = *(people.at(i));
turns into:
Person bob = people.at(i);
and you can access member functions with . instead of -> everywhere, for example:
people.at(k)->setbalance(giveeach);
would turn into:
people.at(k).setbalance(giveeach);
This means getting rid of a lot of unneeded dereferencing of pointers and also of the memory leak you previously would have had.
For me, it seems that you are getting that error since opening input file fin is not successful. To check it, add the following line after you define fin variable:
ifstream fin ("gift1.in");
if(!fin) {
cout << "Error opening input file.\n";
}
In any case, it's always a good practice to check if the file is opened successfully.
I want to add a theater object into a boxoffice object in a C++ code. When I try to add it in main code, first one is added successfully. But a segmentation fault occurs for second and obvioulsy other theater objects. Here is the add function;
#include <iostream>
#include <string>
#include "BoxOffice.h"
using namespace std;
BoxOffice::BoxOffice()
{
sizeReserv = 0;
sizeTheater = 0;
theaters = new Theater[sizeTheater];
reserv = new Reservation[sizeReserv];
}
BoxOffice::~BoxOffice(){}
void BoxOffice::addTheater(int theaterId, string movieName, int numRows, int numSeatsPerRow){
bool theaterExist = false;
for(int i=0; i<sizeTheater; i++)
{
if(theaters[i].id == theaterId)
{
theaterExist=true;
}
}
if(theaterExist)
cout<<"Theater "<<theaterId<<"("<<movieName<<") already exists"<< endl;
else
{
++sizeTheater;
Theater *tempTheater = new Theater[sizeTheater];
if((sizeTheater > 1)){
tempTheater = theaters;
}
tempTheater[sizeTheater-1] = Theater(theaterId,movieName,numRows,numSeatsPerRow);
delete[] theaters;
theaters = tempTheater;
cout<<"Theater "<<theaterId<<"("<<movieName<<") has been added"<< endl;
cout<<endl;
delete[] tempTheater;
}
}
And I get segmentation fault on this line;
tempTheater[sizeTheater-1] = Theater(theaterId,movieName,numRows,numSeatsPerRow);
This is Theater cpp;
#include "Theater.h"
using namespace std;
Theater::Theater(){
id=0;
movieName="";
numRows=0;
numSeatsPerRow=0;
}
Theater::Theater(int TheaterId, string TheaterMovieName, int TheaterNumOfRows, int TheaterNumSeatsPerRow)
{
id = TheaterId;
movieName = TheaterMovieName;
numRows = TheaterNumOfRows;
numSeatsPerRow = TheaterNumSeatsPerRow;
theaterArray = new int*[TheaterNumOfRows];
for(int i=0;i<TheaterNumOfRows;i++)
theaterArray[i]= new int[TheaterNumSeatsPerRow];
for(int i=0; i<TheaterNumOfRows;i++){
for(int j=0;j<TheaterNumSeatsPerRow;j++){
theaterArray[i][j]=0;
}
}
}
This is header file of Theater;
#include <iostream>
#include <string>
using namespace std;
class Theater{
public:
int id;
string movieName;
int numRows;
int numSeatsPerRow;
int **theaterArray;
Theater();
Theater(int TheaterId, string TheaterMovieName, int TheaterNumOfRows, int TheaterNumSeatsPerRow);
};
And this is how i call add functions;
BoxOffice R;
R.addTheater(10425, "Ted", 4, 3);
R.addTheater(8234, "Cloud Atlas", 8, 3);
R.addTheater(9176, "Hope Springs",6,2);
The problematic lines are these:
if((sizeTheater > 1)){
tempTheater = theaters;
}
First you allocate memory and assign it to tempTheater, but here you overwrite that pointer so it will point to the old memory. It does not copy the memory. Since the code is for a homework assignment, I'll leave it up to you how to copy the data, but I do hope you follow the rule of three for the Theater class (as for the BoxOffice class) which will make it very simple.
Also, there's no need to allocate a zero-size "array", just make the pointers be nullptr (or 0).
I am very new to object oriented programming, pointer use and allocating memory in C++. I am working on an assignment for class and initially I had it pass the first three tests listed below by having an array, grade_array, that in the addScore function looked like grade_array[count -1] = grade. Then it would be used in the mean function.
I know this is not the correct way to go about this because I was getting seg faults, so I know I need to have an array, then create a new array (twice the size) that allocates more memory so that I can put the values of the first one into the new one, and then delete to not get memory leaks. The real problem I am having is I do not know if I am even close to correct on the way I am doing this. The error I am getting:
Running cxxtest tests (5 tests)testrunner(85436) malloc: *** error for object 0x107a87970: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
make: *** [test] Abort trap: 6
I have seen a lot of people having similar problems and posting about them on this very site I just cannot seem to fix mine. I saw that it could be that I made a new pointer and tried to them have them point to the same thing so when one deletes the other has nothing to delete or that my initializer is wrong as it doesn't do much. Like I said, very new to the topic so sorry if I have a million questions and so many errors. I have spent a lot of time on this already and was hoping I could maybe get some advice before I waste more time, thanks in advance!
Gradebook.h
#ifndef GRADEBOOK_H
#define GRADEBOOK_H
#include <string>
using namespace std;
class Gradebook {
public:
Gradebook();
Gradebook(const string& filename);
Gradebook(const Gradebook& that);
virtual ~Gradebook();
void initCount();
void addScore(double grade);
double getScoreAt(int i);
int getCount(int i);
string getSourceFile();
double getMean(); // change back to double
double getMin();
double getMax();
double getMedian();
double getStdDev();
int scoresInRange(double low, double high);
private:
string filename;
int* grade_array;
int new_size;
int count;
int count_tracker;
int* grade_point;
};
#endif
Gradebook.cpp
void Gradebook::initCount(){
count = 0;
}
Gradebook::Gradebook() {
}
Gradebook::Gradebook(const string& filename) : filename(filename) {
//this->filename = filename; // i beleive that filename(filename) does this line
//grade_array = new int[this->getCount(0) +1];
}
Gradebook::Gradebook(const Gradebook& that) {
}
Gradebook::~Gradebook() {
for ( int i = 0; i < this->getCount(0); i ++){
delete &grade_array[i];
}
delete grade_array;
}
void Gradebook::addScore(double grade) {
int count_tracker = this->getCount(1); //number of elements in array currently
// grade_array = new int[count_tracker ];
// grade_array = new int[1]; // grade_array is just a *array
grade_array[count_tracker -1 ] = grade; // array[0] is first not array[1]
new_size = count_tracker * 2;
int* new_array = new int[new_size];
for (int i = 0; i < count_tracker ; i++) {
new_array[i] = grade_array[i];
}
delete[] grade_array;
grade_array = new_array;
count_tracker = new_size;
}
double Gradebook::getScoreAt(int i) {
return grade_array[i];
}
int Gradebook::getCount(int i) {
if (i == 1){
count = count + 1;
}
else{
//don't want to add to the actual count
}
return count;
}
string Gradebook::getSourceFile() {
//ifstream foo;
//foo.open(filename);
return filename;
}
double Gradebook::getMean() {
double mean = 0;
count_tracker = this->getCount(0);
for (int i = 0; i < count_tracker ; i++){
//mean = (*(&(grade_array[i])- (bit_count))) + mean;
mean = grade_array[i] + mean;
}
return (mean/count_tracker);
}
GradebookTest.h
#ifndef GRADEBOOK_TEST_H
#define GRADEBOOK_TEST_H
#include <Gradebook.h>
#include <cxxtest/TestSuite.h>
class GradebookTest : public CxxTest::TestSuite {
public:
void testDefaultConstructor(){
string filename = "data1.txt";
Gradebook a(filename);
TS_ASSERT_EQUALS("data1.txt" , a.getSourceFile());
}
void testAddOne() {
Gradebook gb;
gb.initCount();
gb.addScore(110);
TS_ASSERT_EQUALS(120, gb.getScoreAt(1));
TS_ASSERT_DELTA(110, gb.getMean(), 0.001);
TS_ASSERT_EQUALS(4, gb.getCount(0) );
}
void testAddMultiple() {
Gradebook gb;
gb.addScore(75);
TS_ASSERT_EQUALS(1, gb.getCount(0) );
gb.addScore(85);
TS_ASSERT_EQUALS(2, gb.getCount(0));
TS_ASSERT_DELTA(85, gb.getMean(), 0.001);
}
#endif
I think the following is wrong
for ( int i = 0; i < this->getCount(0); i ++){
delete &grade_array[i];
}
You don't need this for loop since you only allocate memory for grad_array. One delete grade_array; is enough.