C++ program crashing (has something to do with with dynamic memory) - c++

I'm having the weird crashing that occurs everytime it goes to the for loop to initialize each position to undefined. Can anyone shine light on why this is happening?
#include
#include
#include
using namespace std;
class MyPhoneBook
{
public:
MyPhoneBook(int, string, string, string, string);
MyPhoneBook();
~MyPhoneBook();
void initialise(int, int, string, string, string, string);
bool search(string&, int);
bool find_free_pos();
void add();
void remove();
void display(int);
friend istream& operator >> (istream& in, MyPhoneBook& ph);
friend ostream& operator << (ostream& out, MyPhoneBook& ph);
private:
int *recordid;
int *status; // -1 is no longer at this number, 0 is blocked, 1 is not blocked, 2 is free
string *name, *areacode, *number, *group;
};
int main(int argc, char** argv)
{
cout << "test 1" << endl;
MyPhoneBook *myphbk; // pointer that will point to an object of a MyPhoneBook class
myphbk = new MyPhoneBook[100]; // now its using dynamic memory
cout << "test 2" << endl; //just for testing
int pos = 0;
for(pos = 0; pos < 100; pos++) // initializing everything to undefined, and position to free (position is the second parameter sended in)
{
myphbk[pos].initialise( (pos+1) , 2 , "Undefined" , "Undefined" , "Undefined" , "Undefined");
}
cout << "test 3" << endl; //just for testing
}
return 0;
void MyPhoneBook::initialise(int recordid_,int status_, string name_, string areacode_, string number_, string group_)
{
//now assign them to private member variables
*recordid = recordid_;
*status = status_;
*name = name_;
*areacode = areacode_;
*number = number_;
*group = group_;
//end of assigning
}
does anyone have any idea why can't my program reach the cout << "test 3" << endl part of the program without crashing?

Since you did not paste the constructor of MyPhoneBook i can only guess, but the problem could be the lines
*recordid = recordid_;
*status = status_;
if you did not assign a valid address to recordid and status in the constructor, e.g. by
recordid = new int;
status = new int;
You might want to declare those member variables as a simple int.

Related

Losing a data member of a base class after the constructor is called

I have been working on a project and had no problems until today where I lost a class data member after the constructor is called. I could not pinpoint where the change happens. I have several classes for cars. The classes related to the cars are in the code block below. After all the cars are created in the class RegistrationSystem they are stored in an array. however, while calling a display function in RegistrationSystem the first car loses the color value. In the class RegistrationSystem the first Pickup in the class stores the value until the constructor is complete. After the constructor ends, the color value string shows " " in the debugger.
class Car {
protected:
string color;
public:
Car(string c) { color = c; };
string getColor(void) { return color; }
friend ostream& operator<<(ostream& outStream, const Car& car) {
cout << car.color;
return outStream;
}
};
class Pickup : public Car {
public:
Seat *frontSeat = new Seat(FRONT_SEAT_CREDIT);
Pickup(string c) : Car(c) {}
};
class Compact : public Car {
public:
Seat *frontSeat = new Seat(FRONT_SEAT_CREDIT);
Seat *sideBackLeftSeat = new Seat(BACK_SEAT_COMPACT_CREDIT);
Seat *sideBackRightSeat = new Seat(BACK_SEAT_COMPACT_CREDIT);
Compact(string c) : Car(c) {}
};
class Sedan : public Car {
public:
Seat *frontSeat = new Seat(FRONT_SEAT_CREDIT);
Seat *sideBackLeftSeat = new Seat(SIDE_BACK_SEDAN_CREDIT);
Seat *sideBackRightSeat = new Seat(SIDE_BACK_SEDAN_CREDIT);
Seat *middleBackSeat = new Seat(MID_BACK_SEDAN_CREDIT);
Sedan(string c) : Car(c) {}
};
class RegistrationSystem {
private:
string file_name;
int menu_response;
Reservation *reservations[24] = { NULL };
Passenger *rowers[24];
Pickup *pickup_cars[3];
Compact *compact_cars[3];
Sedan *sedan_cars[3];
// Displays the Layouts
void displaySeatArrangements(void);
// Saves the information in the file
void saveToFile(void);
// Find the rower in array rowers
Passenger* findRower(string);
// Displays the menu for the seat choice of a car type
bool displayCarSeatingChoiceMenu(string);
// Make a reservation in the system
bool makeReservation(string, string, int, Passenger&);
// Delete a reservation
bool deleteReservation(int);
// Print Reservations
void saveReservationsToFile(void);
// Sub functions for makeReservation()
bool makePickupReservation(Pickup*, Passenger, int&, string, string);
bool makeCompactReservation(Compact*, Passenger, int&, string, string);
bool makeSedanReservation(Sedan*, Passenger, int&, string, string);
public:
RegistrationSystem(void);
void chooseOperation(void);
Passenger* getPassengers(void) { return *rowers; }
friend ostream& operator<<(ostream&, const RegistrationSystem&);
friend istream& operator>>(istream&, RegistrationSystem&);
};
The display function has a line:
<< setw(8) << *(pickup_cars[index]) << setw(8) << *(compact_cars[index]) << setw(11) << *(sedan_cars[index]) << endl
where the *(pickup_cars[index]) is set to " " and the seat value gives error = read memory from 0x6 failed (0 of 4 bytes read). That is also set to NULL.
Here is the code of the RegistrationSystem constructor:
RegistrationSystem::RegistrationSystem(void) {
file_name = "seat_credits.txt";
menu_response = 0;
ifstream inFile(file_name);
if(!inFile.is_open()) {
cout << "Error opening file. Terminating...";
exit(1);
}
// Read file to set passengers and their credits in rowers array
int count = 0;
while(!inFile.eof() && count < 24) {
string first, last;
int credits;
inFile >> first >> last >> credits;
string fullName = first + ' ' + last;
rowers[count] = new Passenger(fullName, credits);
count++;
}
// Assign all the cars to the arrays
pickup_cars[0] = new Pickup("PURPLE");
pickup_cars[1] = new Pickup("YELLOW");
pickup_cars[2] = new Pickup("RED");
compact_cars[0] = new Compact("GREEN");
compact_cars[1] = new Compact("BLUE");
compact_cars[2] = new Compact("YELLOW");
sedan_cars[0] = new Sedan("RED");
sedan_cars[1] = new Sedan("GREEN");
sedan_cars[2] = new Sedan("BLUE");
inFile.close();
}
The problem occurred when the input file stream was still open and I was creating new instances and assigning their addresses to pointers before I closed the file. After I switched the order and closed the file, then assigned pointers the addresses of the new objects the problem went away.
These operations were happening inside of the constructor of the RegistrationSystem class. Here is the new code:
RegistrationSystem::RegistrationSystem(void) {
file_name = "seat_credits.txt";
menu_response = 0;
ifstream inFile(file_name);
if(!inFile.is_open()) {
cout << "Error opening file. Terminating...";
exit(1);
}
// Read file to set passengers and their credits in rowers array
int count = 0;
while(!inFile.eof() && count < 24) {
string first, last;
int credits;
inFile >> first >> last >> credits;
string fullName = first + ' ' + last;
rowers[count] = new Passenger(fullName, credits);
count++;
}
inFile.close();
// Assign all the cars to the arrays
pickup_cars[0] = new Pickup("PURPLE");
pickup_cars[1] = new Pickup("YELLOW");
pickup_cars[2] = new Pickup("RED");
compact_cars[0] = new Compact("GREEN");
compact_cars[1] = new Compact("BLUE");
compact_cars[2] = new Compact("YELLOW");
sedan_cars[0] = new Sedan("RED");
sedan_cars[1] = new Sedan("GREEN");
sedan_cars[2] = new Sedan("BLUE");
}
The line inFile.close() was placed after all the array assignments. Moving it above them solved the problem of losing the first data member of my Pickup object.

Retrive data using pointers to objects in c++

This a menu based program to create a database of people and for performing operations on their name. After compilation, I am able to add a person successfully using the add function of Person class but when I retrieve the list of the added people using list function it shows garbage values instead of showing the entered names. It's the question no. 4(lab 4) in the below give doc.
https://drive.google.com/open?id=18cR9bgPlqM6q-kXBIcxg5Hpj04bkZMnW&authuser=0
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
using namespace std;
class Person
{
const char *name;
public:
Person(const char* n)
{
name=n;
}
bool search(const char* substr)
{
const char *str=name;
while(*str!='\0')
{ int count=0;
if(*str==*substr)
{ const char *s=substr;
const char *p=str;
while(*s!='\0')
{
if(*p==*s)
{
count++;
p++;
s++;
}
else
break;
}
}
if(count==strlen(substr))
{
cout<<name<<endl;
return true;
}
str++;
}
return false;
}
void print()
{
cout<<name<<endl;
}
~Person()
{
cout << ":)";
}
friend class People;
};
class People
{
Person** array;
int length;
void prompt()
{
cout << "\n'A'-Add a person\n'L'-List all persons\n'S'-Search\n'Q'-Quit\n";
}
public:
People()
{
array = NULL;
length = 0;
}
void add()
{
string m;
cout << "Enter a Name:\n";
cin >> m;
Person s(m.c_str());
if (array == NULL)
array = (Person**)malloc(sizeof(Person*));
else
{
array=(Person**)realloc(array, length*sizeof(Person*));
}
array[length] =new Person(s.name);
array[length]->print();
++length;
}
void list()
{
cout << "\nThe names of the person in the list are:\n";
for (int i = 0; i <length; i++)
{
array[i]->print();
}
}
void search()
{
string a;
int flag = 0;
cout << "\nEnter a string to be found in the names present in the list:\n";
cin >> a;
cout << "\n The names with entered substring are:\n";
for (int i = 0; i <length; i++)
{
bool state=array[i]->search(a.c_str());
if (state)
flag = -1;
}
if (flag == 0)
cout << "\nNone of the names contains the entered substring!!!\n";
}
void menu()
{
char c = 'Y';
while (c != 'Q')
{
cout << "Choose an option(character):\n";
prompt();
cin>>c;
switch (c)
{
case 'A':add();
cout << "Name entered sucessfully!!!\n";
break;
case 'L':list();
break;
case 'S':search();
break;
case 'Q':c = 'Q';
break;
}
}
}
};
int main()
{
People All;
All.menu();
return 0;
}
I am not able to find any mistake in my implementation of add function. What could be the possible reason for malfunctioning of list function?
tl;dr
You store a pointer to the internal memory of string (m). That string gets destroyed at the end of add() so you have pointer to unallocated memory, which causes undefined behaviour.
possible solutions
Best would be to store a std::string instead of a const char * inside Person.
walkthrough
If you want a more detailed analyses: You store a pointer to a string that goes out of scope.
void add()
{
string m; // string is initialized and allocates memory for its content
cout << "Enter a Name:\n";
cin >> m; // read content
Person s(m.c_str()); // m.c_str() retrieves a pointer to the memory allocated by m
//this pointer is stored inside s
if (array == NULL)
{
array = (Person**)malloc(sizeof(Person*));
}
else
{
array=(Person**)realloc(array, length*sizeof(Person*));
}
array[length] = new Person(s.name); // s.name still points to the memory allocated by m
array[length]->print();
++length;
} //At the end of the function m gets destroyed and deallocates its memory
So after the function exits you still have stored the pointer to m.c_str() inside a persons name. This pointer now points to unallocated memory. This memory now may (or may not) be overwritten at any time. You get undefined behaviour and print garbage.

C++: Setters and Getters for Arrays

I am struggling to find the correct format for initializing a (private) array within a class and getting/setting the values from outside the class.
My code is semi-functional, but feels awkward in incorrectly formatted.
It is returning only the first element of the array, I want it to return all the contents. Read code comments for additional details.
Note: This is (a very small part of) a project I am working on for school -- an array must be used, not a vector or list.
student.h
class Student {
public:
// Upon researching my issue, I read suggestions on passing pointers for arrays:
void SetDaysToCompleteCourse(int* daysToCompleteCourse[3]);
int* GetDaysToCompleteCourse(); // Ditto # above comment.
private:
int daysToCompleteCourse[3];
student.cpp
#include "student.h"
void Student::SetDaysToCompleteCourse(int* daysToCompleteCourse) {
// this->daysToCompleteCourse = daysToCompleteCourse; returns error (expression must be a modifiable lvalue)
// Feels wrong, probably is wrong:
this->daysToCompleteCourse[0] = daysToCompleteCourse[0];
this->daysToCompleteCourse[1] = daysToCompleteCourse[1];
this->daysToCompleteCourse[2] = daysToCompleteCourse[2];
}
int* Student::GetDaysToCompleteCourse() {
return daysToCompleteCourse;
}
ConsoleApplication1.cpp
#include "pch.h"
#include <iostream>
#include "student.h"
int main()
{
Student student;
int daysToCompleteCourse[3] = { 1, 2, 3 };
int* ptr = daysToCompleteCourse;
student.SetDaysToCompleteCourse(ptr);
std::cout << *student.GetDaysToCompleteCourse(); // returns first element of the array (1).
}
I gave this my best shot, but I think I need a nudge in the right direction.
Any tips here would be greatly appreciated.
I would say:
// student.h
class Student
{
public:
// If you can, don't use numbers:
// you have a 3 on the variable,
// a 3 on the function, etc.
// Use a #define on C or a static const on C++
static const int SIZE= 3;
// You can also use it outside the class as Student::SIZE
public:
void SetDaysToCompleteCourse(int* daysToCompleteCourse);
// The consts are for "correctness"
// const int* means "don't modify this data" (you have a setter for that)
// the second const means: this function doesn't modify the student
// whithout the const, student.GetDaysToCompleteCourse()[100]= 1 is
// "legal" C++ to the eyes of the compiler
const int* GetDaysToCompleteCourse() const; // Ditto # above comment.
Student()
{
// Always initialize variables
for (int i= 0; i < SIZE; i++) {
daysToCompleteCourse[i]= 0;
}
}
private:
int daysToCompleteCourse[SIZE];
// On GCC, you can do
//int daysToCompleteCourse[SIZE]{};
// Which will allow you not to specify it on the constructor
};
// student.cpp
void Student::SetDaysToCompleteCourse(int* newDaysToCompleteCourse)
{
// It's not wrong, just that
// this->daysToCompleteCourse[0] = daysToCompleteCourse[0];
// use another name like newDaysToCompleteCourse and then you can suppress this->
// And use a for loop
for (int i= 0; i < SIZE; i++) {
daysToCompleteCourse[i]= newDaysToCompleteCourse[i];
}
}
const int* Student::GetDaysToCompleteCourse() const
{
return daysToCompleteCourse;
}
// main.cpp
#include <iostream>
std::ostream& operator<<(std::ostream& stream, const Student& student)
{
const int* toShow= student.GetDaysToCompleteCourse();
for (int i= 0; i < Student::SIZE; i++) {
stream << toShow[i] << ' ';
}
return stream;
}
int main()
{
Student student;
int daysToCompleteCourse[3] = { 1, 2, 3 };
// You don't need this
//int* ptr = daysToCompleteCourse;
//student.SetDaysToCompleteCourse(ptr);
//You can just do:
student.SetDaysToCompleteCourse(daysToCompleteCourse);
// On C++ int* is "a pointer to an int"
// It doesn't specify how many of them
// Arrays are represented just by the pointer to the first element
// It's the FASTEST and CHEAPEST way... but you need the SIZE
const int* toShow= student.GetDaysToCompleteCourse();
for (int i= 0; i < Student::SIZE; i++) {
std::cout << toShow[i] << ' ';
// Also works:
//std::cout << student.GetDaysToCompleteCourse()[i] << ' ';
}
std::cout << std::endl;
// Or you can do: (because we defined operator<< for a ostream and a Student)
std::cout << student << std::endl;
}
You can check out it live here: https://ideone.com/DeJ2Nt

Dynamic variable doesnt work

in this code why does the first("invNummer") is always 0, when I initializate it dynamically? When I do it as a static(two) it works.
class Computer {
private:
int invNummer;
char* osName;
int state; // 0 – aus, 1 - an
public:
Computer(int INV, char* OS, int st);
void info() {
cout << invNummer << " " << osName << " " << state << endl;
}
};
Computer::Computer(int INV, char* OS, int st)
: invNummer(INV)
, osName(OS)
, state(st)
{};
int main()
{
Computer* one;
one = new Computer(10, (char*)"Windows", 1);
delete one;
Computer two(9, (char*)"Linux", 0);
one->info();
two.info();
return 0;
}
Output looks like this:
0 Windows 1
9 Linux 0
As #It's_comming_home pointed out to you, your issue is not related to creating the one object dynamically, but to the deletion of that object:
delete one;
When you delete the one object, the pointer is left dangling, ie it is no longer usable. If you try to dereference it afterwards:
one->info();
You will get undefined behavior, like your output shows.
To fix this, just move the deletion of the one object after you invoke its info() method:
one->info();
two.info();
delete one;

Seg fault from constructor

I call this code in main()
for (COwnerList l=b1.ListOwners(10); !l.AtEnd(); l.Next())
cout << l.Surname() << ", " << l.Name () << endl;
for (CCarList l=b1.ListCars("Peter","Smith"); !l.AtEnd(); l.Next ())
cout << l.RZ () << ", " << l.VIN() << endl;
for (COwnerList l=b1.ListOwners(10); !l.AtEnd(); l.Next())
cout << l.Surname() << ", " << l.Name() << endl;
I tried to debug and found out seg fault comes from Constructor of COwnerList
COwnerList CRegister::ListOwners (unsigned int vin) const
{
vector<Car>::const_iterator it;
COwnerList tmp;
it = lower_bound(byVINList.begin(), byVINList.end(), Car("",vin), cmpVIN);
if(it != byVINList.end())
tmp.car = &(*it);
tmp.in = it->owners.end() - it->owners.begin();
return tmp;
}
constructor im calling looks like this:
COwnerList::COwnerList(void)
{
here = car->owners.begin();
i = 0;
in = car->owners.end() - car->owners.begin();
}
interesting is it doesnt crash after 1st for in main(), so there must be something wrong in the code between those 2 for cycles in main(), but i have no idea what it could be i am not modifying anything related to ListOwners() there
EDIT1
Car constructor:
Car::Car( const string & pid,
const unsigned int & pvin = 0,
const string & cname = "",
const string & csurname = "")
{
rz = pid;
VIN = pvin;
name = cname;
surname = csurname;
}
EDIT2
class COwnerList
{
public:
COwnerList(void);
string Name ( void ) const;
string Surname ( void ) const;
bool AtEnd ( void ) const;
void Next ( void );
//vector<pair<string, string> > powners;
const Car *car;
int in;
private:
vector<pair<string, string> >::const_iterator here;
int i;
};
The problem is that the car pointer is not initialized during the call in the COwnerList constructor. In the first loop, you might have got lucky. Things like this happens all the time. Sometimes the OS won't throw a seg fault everytime when you are calling a code which is not allocated yet.
Just put a condition guard in your code like this:
if (car != NULL) {
here = car->owners.begin();
i = 0;
in = car->owners.end() - car->owners.begin();
}
The error is more likely you are modifying the vector after saving that tmp.toto pointer to the vector's internal storage.
Note that when you do tmp.car = &(*it) you are making a pointer towards the internal storage of the vector.
If later you call push_back() on the vector, you cannot rely in the pointers that you had before, because the vector can reallocate its contents in other memory addresses after you call the push_* methods.
Also note that a debugger may not tell the exact line that has to be corrected, even if the crash happens there. The debugger may tell you the first line where the problem is evident, but the cause of the problem may have happened several lines before.