I'm freeing memory twice - C++ - c++

I have done this program where I check if my 'date' class is correct. The problem is that when I run my test program, it returned my the following error:
Error in `./bin/test': double free or corruption (fasttop): 0x00000000019c07c0 *
The job of this class is read and store a 'date'(a year) and a few events (allocated in a string array). For example, a object of this class would be: 1998 EVENT1 EVENT2 EVENT3.
Operator >> reads the next format:1908#Fantasmagorie#The Taming of the Shrew#The Thieving Hand#The Assassination of the Duke of Guise#A Visit to the Seaside
Well, my problem is that I'm deleting some pointer twice or freeing some memmory twice, I have tried a lot of things but I don't know how to fix it (as you can see on my code, I have already tried to set all pointers to 0 when I delete them.):
Date class .h
#ifndef _date_HISTORICA_
#define _date_HISTORICA_
#include <iostream>
#include <string>
#include <cassert>
using namespace std;
class date{
private:
int year;
int eventsNum;
int reserved;
string * str;
void resize(int r);
public:
date();
//date(int a, string *s, int n);
date(const date& d);
~date();
int getAge();
void addEvent(string& s);
friend ostream& operator<<(ostream& os, const date& d);
friend istream& operator>>(istream& is, date& d);
};
#endif
Date Class Code:
#include<iostream>
#include<string>
#include<fstream>
#include<sstream>
#include<date.h>
using namespace std;
void date::resize(int r)
{
assert(r>=0);
if(r!=this->reserved)
{
if(r!=0)
{
string * aux = new string[r];
if(this->reserved>0)
{
int min=this->reserved<r?this->reserved:r;
for(int i=0; i<min; i++)
aux[i]=this->str[i];
delete[] this->str;
this->str=NULL;
}
this->str=aux;
this->reserved=r;
if(this->reserved<this->eventsNum)
this->eventsNum=this->reserved;
} else
{
if(this->reserved>0)
{
delete[] this->str;
this->str=NULL;
}
this->year=0;
this->eventsNum=0;
this->reserved=0;
}
}
}
date::date() : year(0), eventsNum(0), reserved(0), str(0){}
date::date(const date& d)
{
this->year=d.year;
this->eventsNum=d.eventsNum;
this->reserved=d.reserved;
this->str=new string[this->reserved];
for(int i=0; i<this->eventsNum; i++)
this->str[i]=d.str[i];
}
date::~date()
{
this->year=0;
this->eventsNum=0;
this->reserved=0;
if(this->str)
delete[] this->str;
this->str=NULL;
}
int date::getAge(){return this->year;}
ostream& operator<<(ostream& os, const date& d)
{
os << d.year;
for(int i=0; i<d.eventsNum; i++)
os << '#' << d.str[i];
os << endl;
return os;
}
void date::addEvent(string& s){
if (this->eventsNum == this->reserved){
if (this->eventsNum==0)
resize(1);
else
resize(2*this->reserved);
}
this->str[eventsNum]=s;
eventsNum++;
}
istream& operator>>(istream& is, date& d)
{
string line; char c;
is >> d.year >> c;
getline(is, line);
int n=1;
for(int i=0; i<line.length(); i++)
if(line[i]=='#')
n++;
d.eventsNum=n;
d.reserved=d.eventsNum;
delete[] d.str;
d.str=NULL;
d.str=new string[n];
stringstream ss(line);
for(int i=0; i<n; i++)
getline(ss, d.str[i], '#');
return is;
}
Test Program Class:
#include<iostream>
#include<fstream>
#include<cronologia.h>
#include<date.h>
using namespace std;
int main(int argc, char * argv[]){
cout << "STATE: IN PROGRESS" << endl;
cout << "TEST: (2)" << endl;
date d;
ifstream f("./data/name.txt");
while(f >> d)
{
cout << d;
}
date d1;
cin >> d1;
d=d1;
cout << d << endl;
}
Example file (wich should be read by date clas):
1900#Sherlock Holmes Baffled#The Enchanted Drawing
1901#Star Theatre#Scrooge, or, Marley's Ghost
1902#A Trip to the Moon
1903#The Great Train Robbery#Life of an American Fireman
1904#The Impossible Voyage
1905#Adventures of Sherlock Holmes; or, Held for Ransom
1906#The Story of the Kelly Gang#Humorous Phases of Funny Faces#Dream of a Rarebit Fiend
1907#Ben Hur#L'Enfant prodigue
1908#Fantasmagorie#The Taming of the Shrew#The Thieving Hand#The Assassination of the Duke of Guise#A Visit to the Seaside
Im so sorry for my English!!! :,(

Since there is no assignment overloading in your code, in the line
d=d1;
All the members of d1 will be copied to a new object d by value. Hence there will be two copies of the object date which have the same reference value in their member str. Those two will eventually get out of scope and both will be destructed. The first one will free the allocated memory while the other will try to free that same reference and that is why you get the error.

You need a copy assignment operator:
void swap(date& other)
{
using std::swap;
swap(year, other.year);
swap(eventsNum, other.eventsNum);
swap(reserved, other.reserved);
swap(str, other.str);
}
date::date(const date& d) : year(other.year), eventsNum(other.eventsNum), reserved(other.reserved), str(new string[other.reserved])
{
for(int i = 0; i < this->eventsNum; i++)
this->str[i] = d.str[i];
}
date& date::operator = (const date& d)
{
swap(*this, d);
return *this;
}
Might also be nice to provide a move constructor..

Related

Trying to read two files in the same time

I am playing with threads but I don't know why this code doesn't work properly. It has to read two files(the names of the files come from keyboard) and then show the contents in the console. Could you tell me where is the problem?
#include<iostream>
#include<fstream>
#include<thread>
#include<string>
#include<vector>
using namespace std;
mutex mtx;
class eu
{
string filename;
string buffer;
public:
eu() {};
void citire(string filename)
{
this->filename = filename;
ifstream f(filename);
while (f.eof())
{
string ceva;
f >> ceva;
buffer = buffer + ceva;
}
f.close();
}
/*void operator()() it doesn't work either in this way
{
this->citire(filename);
}*/
friend ostream &operator<<(ostream& os, eu&n);
//~eu();
};
ostream& operator<<(ostream& os, eu&n)
{
os << n.buffer;
return os;
}
//threads.push_back(std::thread(&C::increase_member,std::ref(bar),1000));
int main()
{
vector<thread>instante;
string nume;
eu n;
for (int i = 0; i <2; i++)
{
cin >> nume;
instante.push_back(thread(&eu::citire, n, nume));
}
for (auto& th : instante) th.join();
cout << n;
}

Overloading i/o operators in C++ for polynomials

I got this project where I have to overload the i/o operators to read and write polynomials. Unfortunately I can't seem to get it to work.
I have the header file:
#ifndef POLYNOMIAL_H
#define POLYNOMIAL_H
#include <iostream>
using namespace std;
class Polynomial
{
public:
Polynomial();
Polynomial(int degree, double coef[]);
int degree;
double coef[ ];
friend istream& operator>>(istream&,Polynomial& );
friend ostream& operator<<(ostream&,const Polynomial&);
virtual ~Polynomial();
};
#endif // POLYNOMIAL_H
and the cpp file:
#include "Polynomial.h"
#include<iostream>
#include<string>
using namespace std;
Polynomial::Polynomial()
{
//ctor
}
Polynomial::~Polynomial()
{
//dtor
}
Polynomial::Polynomial(int d, double c[])
{
degree = d;
double coef [degree+1];
for(int i = 0; i < d+1; i++)
{
coef[i] = c[i];
}
}
istream& operator>>(istream& x, const Polynomial& p)
{
cout<<"The degree: ";
x>>p.degree;
for(int i = 0; i < p.degree+1; i++)
{
cout<<"The coefficient of X^"<<i<<"=";
x>>p.coef[i];
}
return x;
}
ostream& operator<<(ostream& out, const Polynomial& p)
{
out << p.coef[0];
for (int i = 1; i < p.degree; i++)
{
out << p.coef[i];
out << "*X^";
out << i;
}
return out;
}
In the name I am trying to read a polynomial and then to write another one:
#include <iostream>
using namespace std;
#include "Polynomial.h"
int main()
{
Polynomial p1();
cin >> p1;
int degree = 2;
double coef [3];
coef[0]=1;
coef[1]=2;
coef[3]=3;
Polynomial p(degree, coef);
cout<<p;
return 0;
}
When I run the program it just freezes and I can't seem to find the error.
Any ideas?
Polynomial::Polynomial(int d, double c[])
{
degree = d;
double coef [degree+1];
for(int i = 0; i < d+1; i++)
{
coef[i] = c[i];
}
}
Here, you create local array coef (with non-standard C++ btw) and then assign to it. Your member coeff is not initialized to anything meanigfull (and makes little sense the way it is right now in the first place).
Instead of double coef[] you should use std::vector like this:
struct polynomial {
std::vector<double> coef;
// No need for member varaible degree, vector knows its lengths
polynomial (const std::vector<double> &coeffs) : coef (coeffs) {}
};
And then define all other constructors you need to do something meaningful. Alternatively, you can leave out constructors entirely and directly assign the coefficient vector. Then you can for example functions like
int degree (const polynomial &p) {
return p.coef.size() - 1;
}
or
std::ostream &operator << (std::ostream &out, const polynomial p) {
if (p.coef.size() == 0) {
out << "0\n";
return out;
}
out << p.coeff[0];
for (int i = 1; i < p.coef.size(); ++i)
out << " + " << p.coef[i] << "*X^i";
out << "\n";
return out;
}
(1)
double coef[];
This is non-standard approach to have un-sized/dynamic-sized array on stack. You better give the array some size, OR make it a pointer and allocate memory yourself; OR use vector<double>
(2)
You are creating a local variable in constructor, which will hide the member-variable in class. If you are using pointer approach, you need to allocate it properly here in constructor. With either approach, you should initialize the (member) variable coef with zeros, ideally.
(3)
Polynomial p1();
This effectively declares a function named p1 which would return a Polynomial and not a variable of tyoe Polynomial. You may want to use:
Polynomial p1;

C++ ostream output wrong [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I have a problem and I can't solve it.
note: I can't use any string/strlen/strcmp and such functions
My problem is when I'm trying to print obj after cin, when I don't put him value it prints garbage, and if I put value it change it by cin it print it well.
#ifndef __STRING_H__
#define __STRING_H__
#include <iostream>
using namespace std;
class String {
private:
char* Str; //pointer to string
int Str_s; // size of string public:
String(char* str = NULL);
~String();
void const print() const; //check
//~~~~~~~~~~~~~~~~~~
// operators
//~~~~~~~~~~~~~~~~~
String& operator=(const String& str);
bool operator==(const String& s) const;
bool operator!=(const String& s) const;
void operator-=(const char c);
void operator+=(const char c);
char& operator[](const int index) const;
//~~~~~~~~~~~~~~~~~~
// i/o ~~ operators
//~~~~~~~~~~~~~~~~~
friend ostream& operator<<(ostream&, const String& s);
friend istream& operator>>(istream&, String& s);
//~~~~~~~~~~~~~~~~~~
// arrange method
//~~~~~~~~~~~~~~~~~
void Letters(); // arrange all letter in sentence
void Space(); //remove all unwanted spaces
void Set_Str_s(int num) {
this->Str_s = num;
}
int Get_Str_s() {
return this->Str_s;
}
//~~~~~~~~~~~~~~~~~~
// methods
//~~~~~~~~~~~~~~~~~
char const* STR() {
return Str;
}
};
#endif
ostream& operator<<(ostream& output, const String& s) {
//char *c = s.Str;
//output << c << endl;
for (int i = 0; i < s.Str_s; i++) {
cout << s.Str[i];
}
return output;
}
istream& operator>>(istream& input, String& s) {
if (s.Str == NULL) {
s.Str_s = 0;
char temp[BUFFER];
int i = 0, j = 0;
cin.getline(temp, BUFFER);
while (temp[i] != NULL) {
s.Str_s++;
i++;
}
//s.Str = new char[s.Str_s];
s.Str = temp;
} else {
input >> s.Str;
}
return input;
}
#include <iostream>
using namespace std;
#include "string_head.h"
#include "Definition_head.h"
#include "Menu_head.h"
int main() {
char* c = "hi";
char* h = "lilo";
String s, m(c);
cin >> s;
cin >> m;
cout << s;
cout << endl;
cout << m;
}
The following line is a problem:
s.Str = temp;
you are storing a pointer to a local array that will be deleted when the function returns. Use something like:
s.Str = strdup(temp);
If your platform doesn't support strdup, you can implement it. It's not too hard.
The following line is also a problem:
input >> s.Str;
If there isn't enough memory to hold the string being read, you will be writing into memory that you are not supposed to.

Overloading operator =, error in reading string

I am trying to write an overload to the = operator so that it allows you directly assign one student object to another student object. So it will copy all the private data members. Here is what I have so far.
.h
#ifndef PROJECT3HEADER_H
#define PROJECT3HEADER_H
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
class Student
{
public:
Student();
void Setlname(string lname);
void Setfname(string fname);
void SetAverage(float Average);
void SetLettergrade(char lettergrade);
void SetTestScore1(float score1);
void SetTestScore2(float score2);
void SetTestScore3(float score3);
void SetTestScore4(float score4);
void SetTestScore5(float score5);
string Getlname()const;
string Getfname()const;
float GetAverage()const;
char GetLetterGrade()const;
float GetScore1()const;
float GetScore2()const;
float GetScore3()const;
float GetScore4()const;
float GetScore5()const;
//void operator = (const Student & rhs);
Student operator=(const Student &rhs);
private:
string lname,fname;
float testScore[5];
float Average;
char lettergrade;
};
ostream & operator << (ostream &, const Student & pt);
//istream& operator >> (istream& in, Student& pt);
#endif
Studentmem.cpp
#include "Project3Header.h"
#include <iostream>
#include <string>
using namespace std;
Student::Student()
{
lname="";
fname="";
Average=0;
lettergrade=' ';
testScore[0]=0,testScore[1]=0,testScore[2]=0,testScore[3]=0,testScore[4]=0;
}
void Student::Setlname(string lname1){
lname=lname1;
}
void Student::Setfname(string fname1){
fname=fname1;
}
void Student::SetAverage(float average1){
Average=average1;
}
void Student::SetLettergrade(char lettergrade1){
lettergrade=lettergrade1;
}
void Student::SetTestScore1(float score1){
testScore[0]=score1;
}
void Student::SetTestScore2(float score2){
testScore[1]=score2;
}
void Student::SetTestScore3(float score3){
testScore[2]=score3;
}
void Student::SetTestScore4(float score4){
testScore[3]=score4;
}
void Student::SetTestScore5(float score5){
testScore[4]=score5;
}
string Student::Getlname()const {
return lname;
}
string Student::Getfname()const {
return fname;
}
float Student::GetAverage() const{
return Average;
}
char Student::GetLetterGrade()const{
return lettergrade;
}
float Student::GetScore1() const{
return testScore[0];
}
float Student::GetScore2() const{
return testScore[1];
}
float Student::GetScore3() const{
return testScore[2];
}
float Student::GetScore4() const{
return testScore[3];
}
float Student::GetScore5() const{
return testScore[4];
}
Student Student::operator=(const Student &rhs){
lname = rhs.lname;
fname = rhs.fname;
for (int i = 0; i < 5; i++){
testScore[i] = rhs.testScore[i];
}
return *this;
}
std::ostream& operator<<(std::ostream& out, Student const& obj)
{
out << "Lname: " << obj.Getlname() << "\n";
out << "fname: " << obj.Getfname() << "\n";
out << "Average: " << obj.GetAverage() << "\n";
out << "Grade: " << obj.GetLetterGrade() << "\n";
return out;
}
But when I try to use it in the main I get an error... error reading characters of string.
here is a little of my main
#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>
#include "Project3Header.h"
using namespace std;
//Tyler Smith
void StdInfo(Student array[], int size);
Student * MakeStudentArray(int size);
int main(){
ifstream inData;
int size = 0;
int highsize = 0;
char data[65535];
inData.open("F:\\grade.dat");
if (!inData)
{
cout << "Error opening file.\n";
cout << "Perhaps the file is not where indicated.\n";
return 1;
}
while (inData.getline(data, 65535)) {
size++;
}
inData.close();
cout << size;
Student s1;
Student * ptArr;
ptArr = MakeStudentArray(size);
for (int i = 0; i < size; i++){
ptArr[i]= s1;
}
StdInfo(ptArr,size);
/* for (int i = 0; i < size; i++){
cout << ptArr[i].Getlname() << ptArr[i].Getfname(); //<< ptArr[i].Get() << endl;
}*/
cout << ptArr[2].Getfname();
return 0;
}
Student * MakeStudentArray(int size)
{
return new Student[size];
}
void StdInfo(Student array[], int size){
ifstream in;
in.open("F:\\grade.dat");
string fname1,lname1="";
int Score1, Score2, Score3, Score4, Score5=0;
for (int i = 0; i < size; i++) {
in >> lname1;
in >> fname1;
in >> Score1;
in >> Score2;
in >> Score3;
in >> Score4;
in >> Score5;
array[i].Setlname(lname1);
array[i].Setfname(fname1);
array[i].SetTestScore1(Score1);
array[i].SetTestScore2(Score2);
array[i].SetTestScore3(Score3);
array[i].SetTestScore4(Score4);
array[i].SetTestScore5(Score5);
array[i] = array[i + 1];
//for (int j = 0; j < 5; j++) {
//in >> array[i].testScore[j];
//}
}
}
When I try it simply will not work. When I do it in debug mode it stops at the overloading operator and stays "rhs error reading characters of string"
The essense of your problem is not the (unconventional) assignment operator, but the MakeStudentArray function.
I hardcoded the size to 10, rather than reading it from a file, and used
Student * MakeStudentArray(int size)
{
return new Student[size];
}
taking care to call delete [] ptArr; after I was done in main (worrying about exceptions as I did) and all was well.
Your version allocates Students (maybe all over the heap), rather than an array.
If I change the question code you posted in main to
for (int i = 0; i < size; i++){
ptArr[i].operator= (s1);
//^------- you said 0, right?
}
then I get a problem. This is because the for loop assumes the "array" is contiguous, but your function newed an array of points, not an array of Students, so it walks into goodness only knows where when it tries to loop over the "array".
Using my suggestion version should solve the problem, since it allocates an array using new[size] and also makes it easier to delete.
Edit 1:
With the rest on main now posted, perhaps you do keep trying to set ptArr[0] several times in the loop, but then calling StdInfowill try to walk an "array" and will give you the error. If you wish to index into an array, using [] it must be contiguous, so the allocation function, MakeStudentInfo will still be the cause of the problem.
Edit2:
Now there is even more code, look at your StdInfo function. Without the extra details it does this:
for (int i = 0; i < size; i++) {
//...
array[i] = array[i + 1];
}
What are you trying to achieve here? It looks like set the current array[i] to something we haven't got to yet. Once i gets to size i+1 will be off the end of your array.
Removing that line would be a good idea.
The assignment operator should return a reference to the assigned object, not a copy. Also think about using the copy & swap idiom
Student& Student::operator=(const Student &rhs){

cannot swap objects in an array in C++

i am new to C++ and stuck in the swap stuff
the code below is a program of sort employee names in alphbetical order and print out the orginal one and sorted one ,but the
swap method doesn't work
the two output of printEmployees is excatly the same, can anyone help me? thx
#include <iostream>
#include <string>
#include <iomanip>
#include <algorithm>
using namespace std;
class employee
{
/* Employee class to contain employee data
*/
private:
string surname;
double hourlyRate;
int empNumber;
public:
employee() {
hourlyRate = -1;
empNumber = -1;
surname = "";
}
employee(const employee &other) :
surname(other.surname),
hourlyRate(other.hourlyRate),
empNumber(other.empNumber){}
void setEmployee(const string &name, double rate,int num);
string getSurname() const;
void printEmployee() const;
employee& operator = (const employee &other)
{employee temp(other);
return *this;}};
void employee::setEmployee(const string &name, double rate, int num) {
surname = name;
hourlyRate = rate;
empNumber = num;
}
string employee::getSurname() const { return surname; }
void employee::printEmployee() const {
cout << fixed;
cout << setw(20) << surname << setw(4) << empNumber << " " << hourlyRate << "\n";
}
void printEmployees(employee employees[], int number)
{
int i;
for (i=0; i<number; i++) { employees[i].printEmployee(); }
cout << "\n";
}
void swap(employee employees[], int a, int b)
{
employee temp(employees[a]);
employees[a] = employees[b];
employees[b] = temp;
}
void sortEmployees(employee employees[], int number)
{
/* use selection sort to order employees,
in employee
name order
*/
int inner, outer, max;
for (outer=number-1; outer>0; outer--)
{
// run though array number of times
max = 0;
for (inner=1;
inner<=outer; inner++)
{
// find alphabeticaly largest surname in section of array
if (employees
[inner].getSurname() < employees[max].getSurname())
max = inner;
}
if (max != outer)
{
//
swap largest with last element looked at in array
swap(employees, max, outer);
}
}
}
int main()
{
employee employees[5];
employees[0].setEmployee("Stone", 35.75, 053);
employees[1].setEmployee
("Rubble", 12, 163);
employees[2].setEmployee("Flintstone", 15.75, 97);
employees[3].setEmployee("Pebble", 10.25, 104);
employees[4].setEmployee("Rockwall", 22.75, 15);
printEmployees(employees, 5);
sortEmployees(employees,5);
printEmployees(employees, 5);
return 0;
}
This code is broken:
employee& operator = (const employee &other)
{employee temp(other);
return *this;}
It should be something like:
employee& operator= (const employee &other)
{
surname = other.surname;
hourlyRate = other.hourlyRate;
empNumber = other.empNumber;
return *this;
}
As told by others, fixing your assignment operator will solve the problem.
I see that you tried to implement operator= in terms of copy constructor but missed to do a swap. You can try the below approach if you want to avoid code duplication in your copy constructor and assignment operator.
employee& operator=(const employee& other)
{
employee temp(other);
swap(temp);
return *this;
}
void swap(employee& other)
{
std::swap(surname, other.surname);
std::swap(hourlyRate, other.hourlyRate);
std::swap(empNumber, other.empNumber);
}