Segmentation fault with shared pointers - c++

What's wrong with this code (I minimized my whole code)? I can't figure out why pu.useIt(); causes a segmentation fault.
#include <memory>
using namespace std;
class Person {
private:
shared_ptr<string> name;
public:
void setName(shared_ptr<string> name) {
this->name = name;
}
shared_ptr<string> getName() {
return name;
}
};
class PersonCreator {
shared_ptr<Person> person;
public:
void createAmy() {
shared_ptr<string> amysName = make_shared<string>("amy");
person->setName(amysName);
}
};
class PersonUser {
public:
void useIt() {
PersonCreator pc;
pc.createAmy();
}
};
int main()
{
PersonUser pu;
pu.useIt();
return 0;
}

You need to initialize person, now it is empty, default ctor of shared_ptr means that it points to nullptr:
void createAmy() {
shared_ptr<string> amysName = make_shared<string>("amy");
person = std::make_shared<Person>(); // added
person->setName(amysName);
}

Related

C++ I have some seryous issues with inheritance when derived and base class have different types of parameters, like shown below:

Im a newbie in c++ and recently discovered classes;
I learned about constructors, overloading operators, the rule of three and right now i tried to learn inheritance.
I created 4 classes: 2 parents, 2 childs, but i occured some problems in class parent1
This is class parent1:
class parent1{
protected:
float slr;
int age;
char *name;
void set_new_name(char ch[10001]);
public:
parent1()
{
slr=0.0;
age=0;
name=NULL;
}
parent1(char ch[10001], float sl, int ag)
{
slr=sl;
age=ag;
set_new_name(ch);
}
parent1(const parent1 &p1)
{
char temp[10001];
strcpy(temp,p1.name);
if(name != NULL)
delete[] name;
set_new_name(temp);
slr=p1.slr;
age=p1.age;
}
parent1 &operator=(const parent1 &p1)
{
/// same lines as in copy constructor above
return *this;
}
char* get_name() const;
void print1();
~parent1()
{
delete[] name;
}
};
This is his child class, child1:
class child1 : public parent1{
protected:
int id;
void set_id(int j);
public:
child1(): parent1()
{
set_id(0);
}
child1(char ch[10001],float sl, int ag, int j): parent1(ch,sl,ag)
{
set_id(j);
}
child1(const child1 &p2): parent1(p2)
{
set_id(p2.get_id());
}
child1 &operator=(const child1 &p2)
{
set_id(p2.get_id());
parent1::operator=(p2);
}
int get_id() const;
void print2();
};
There is class parent 2:
class parent2{
protected:
char *name1;
char *name2;
void set_new_name1(char ch1[10001]);
void set_new_name2(char ch2[14]);
public:
parent2()
{
name1=NULL;
name2=NULL;
}
parent2(char ch1[10001], char ch2[14])
{
set_new_name1(ch1);
set_new_name2(ch2);
}
parent2(const parent2 &p3)
{
char temp2[10001];
strcpy(temp2,p3.name1);
if(name1 !=NULL)
delete[] name1;
set_new_name1(temp2);
/// .. . same lines as above, this time for name2 and p3.name2
}
parent2 &operator=(const parent2 &p3)
{
/// .. same lines as in copy constructor above
return *this;
}
char* get_name1() const;
char* get_name2() const;
void print3();
~parent2()
{
delete[] name1;
delete[] name2;
}
};
And there is his child, child 2:
class child2: public parent2{
protected:
char *job;
void set_new_job(char ch3[15]);
public:
child2(): parent2()
{
job=NULL;
}
child2(char ch1[10001], char ch2[10001],char ch3[11]): parent2(ch1,ch2)
{
set_new_job(ch3);
}
child2(const child2 &p4): parent2(p4)
{
char temp6[11];
strcpy(temp6, p4.job);
if(job != NULL)
delete[] job;
set_new_job(temp6);
}
child2 &operator=(const child2 &p4)
{
/// same lines as in copy constructor
parent2::operator=(p4);
}
char* get_job() const;
void print4();
~child2()
{
delete[] job;
}
};
As u can see up here, class parent1 have 3 types of parameters ( one float, one int and one char*).
Nonte: set_ functions works ok, get_functions just return class parametes (also works ok) , print functions just print classes parameters ( ex: cout << name1; also works fine)
The problem is that this code refuse to work when i create the objects in main.
First i thought it is operator= being overloaded to many times, bit it turned out to be the float parameter from parent1
There is the main:
char ch[10001]="my name", ch1[10001]="my name 1", ch2[14]="my name 2", ch3[11]="some code";
int ag=10;
float sl=10.1;
parent1 o1;
o1=parent1(ch,sl,ag);
o1.print1();
parent1 o2(o1);
o2.print1();
child1 o3;
o3=child1(ch,sl,ag,3);
o3.print2();
child1 o4;
o4=child1(ch,sl,ag,6);
o4.print2();
o4=o3;
o4.print2();
parent2 o5;
o5=parent2(ch1,ch2);
o5.print3();
child2 o6(ch1,ch2,ch3);
o6.print4();
The only things that seems to make it run are:
deleting the float parameter from parent1;
deleting the last class ; (i really don't know why the last class affect the program)
creating the last object like this : child2 o6(ch1,ch2,ch3); , which is frustrating because it should work like the others;
I know the code i sheared is very long, but Please , Help me to understand what i need to do to solve this stupid bug !
I see at least 3 issues in the code that will lead to a crash/undefined behavior.
First:
parent1(const parent1 &p1)
{
char temp[10001];
strcpy(temp,p1.name);
if(name != NULL) // name isn't initialized yet,
delete[] name; // these 2 lines shouldn't be here
set_new_name(temp);
slr=p1.slr;
age=p1.age;
}
Second: (these ones are reported by the compiler when warnings are enabled)
child1 &operator=(const child1 &p2)
{
set_id(p2.get_id());
parent1::operator=(p2);
return *this; // this line is missing
}
Third:
child2 &operator=(const child2 &p4)
{
char temp7[11];
strcpy(temp7, p4.job);
if(job != NULL)
delete[] job;
set_new_job(temp7);
parent2::operator=(p4);
return *this; // this line is missing
}
The return statement is not "inherited". Each function that's supposed to return something must do so.
With these changes the code runs:
my name
my name
3
6
3
my name 1
my name 2
some code
(Live demo)
Some additional improvement notes:
An array like char ch[10001] can't really be a function argument in C++. When it's used as an argument it silently decays to char *. So you might as well replace all char ch[10001] with const char* ch (and better yet, std::string), to avoid confusion.
Also, there's no point in allocating a temp array. You can just directly do set_new_name(p1.name):
parent1(const parent1 &p1)
{
set_new_name(p1.name);
slr=p1.slr;
age=p1.age;
}
It would be prudent to invest some time in getting familiar with a Debugger. It's all but impossible to make a working application without debugging it. And enable compiler warnings. With GCC use -Wall -Wextra, with MSVC - /W4.
Here's an example of the code using std::string. Thanks to std::string we can follow the rule of 0:
class parent1 {
protected:
float slr = 0;
int age = 0;
string name;
void set_new_name(string const &ch) { name = ch; }
public:
parent1() {}
parent1(string const &name, float slr, int age)
: slr(slr), age(age), name(name) {}
string const &get_name() const { return name; }
void print1();
};
void parent1::print1() { cout << get_name() << '\n'; }
class child1 : public parent1 {
protected:
int id = 0;
void set_id(int j) { id = j; }
public:
child1() : parent1() {}
child1(string const &name, float sl, int ag, int j)
: parent1(name, sl, ag), id(j) {}
int get_id() const { return id; }
void print2();
};
void child1::print2() { cout << get_id() << '\n'; }
class parent2 {
protected:
string name1;
string name2;
void set_new_name1(string const &ch) { name1 = ch; }
void set_new_name2(string const &ch) { name2 = ch; }
public:
parent2() {}
parent2(string const &name1, string const &name2)
: name1(name1), name2(name2) {}
string const &get_name1() const { return name1; }
string const &get_name2() const { return name2; }
void print3();
};
void parent2::print3() {
cout << get_name1() << '\n';
cout << get_name2() << '\n';
}
class child2 : public parent2 {
protected:
string job;
void set_new_job(string const &ch) { job = ch; }
public:
child2() : parent2() {}
child2(string const &name1, string const &name2, string const &job)
: parent2(name1, name2), job(job) {}
string const &get_job() const { return job; }
void print4();
};
void child2::print4() { cout << get_job() << '\n'; }
And this works equally well.

Segmentation fault on base class constructor

Why does it produce a segmentation fault when I create a Rectangle object? I'm thinking that there is something about my constructors that is incorrect but I don't have enough experience in C++ to identify what.
#include <string>
#include <map>
using namespace std;
class Shape {
private:
string name;
string property_name;
map<string,double> parameters;
public:
Shape(){
}
void set_name(string n){
name=n;
}
string set_property_name(string s){
property_name=s;
}
void set_parameter(string p, double n){
parameters[p]=n;
}
double get_parameter(string p) {
return parameters[p];
}
virtual double get_property() = 0;
};
class Shape2D: public Shape {
public:
Shape2D() {
set_property_name("area");
}
};
class Rectangle: public Shape2D {
public:
Rectangle() {
set_name("rectangle");
set_parameter("length",0);
set_parameter("base",0);
}
double get_property() {
return get_parameter("length") * get_parameter("base");
}
};
int main() {
Shape * user_shape;
user_shape=new Rectangle();
return 0;
}
Because your string set_property_name(string s) have no return and is undefined behavior

check object existance when function retuning pass by reference

I have very basic issue and have following code. In rare cases, we are not able to call setDriver(set driver object) and call getDriver function for calling driver class function which resultant memory crash( as setdriver has not set). is it possible to check getdriver object. I have tried to set NULL but as we are returning reference it's not appropriate/feasible.
include<iostream>
#include<string>
using namespace std;
class Driver {
private:
string name;
public:
void setname(string name);
void display();
};
void Driver::setname(string name)
{
this->name = name;
}
void Driver::display()
{
cout<<" This driver is .."<<name<<endl;
}
class sample {
protected:
Driver *m_d;
public:
void setDriver(Driver *driver);
Driver& getDriver();
};
void sample::setDriver(Driver *driver)
{
m_d = driver;
}
Driver& sample::getDriver()
{
return *m_d;
}
int main()
{
sample s;
Driver *d = new Driver;
d->setname("test");
s.setDriver(d);
Driver &d1 = s.getDriver();
// How can I check if d1 is exist or not
d1.display();
}
After getting input from below discussion, I have modified code into following way. will it be correct solution?
#include<iostream>
#include<string>
using namespace std;
class Driver {
private:
string name;
public:
void setname(string name);
void display();
};
void Driver::setname(string name)
{
this->name = name;
}
void Driver::display()
{
cout<<" This driver is .."<<name<<endl;
}
class sample {
protected:
Driver *m_d;
public:
void setDriver(Driver *driver);
Driver& getDriver();
sample();
};
sample::sample()
{
m_d = NULL;
}
void sample::setDriver(Driver *driver)
{
m_d = driver;
}
Driver& sample::getDriver()
{
if(m_d)
return *m_d;
else
throw "Error";
}
int main()
{
sample s;
Driver *d = new Driver;
d->setname("test");
s.setDriver(d);
try{
Driver &d1 = s.getDriver();
d1.display();
}
catch(...)
{
cout<<" object is not prsent"<<endl;
}
References can't point to nothing so I suggest two options:
a) throw an exception - this for me is clearly the best solution; this is an edge case and very appropriate for exception handling
b) Include a method driver.isLoaded() which the caller can check - in the case when you can't allocate a driver return a stub driver which returns this value as false
Alternately you need to change the nature of the call to return a pointer (so that you can return null) or pass your driver as a reference parameter and return a boolean to indicate success. Neither of these options seems as good as a above to me.
A safe way to don't have to check if pointer is null is to force it to never be:
class sample {
public:
// No default constructor
explicit sample(Driver &driver) m_d(&driver) {}
void setDriver(Driver &driver) { m_d = &driver; }
Driver& getDriver() { return *m_d; }
private:
Driver *m_d;
};
Usage:
int main()
{
Driver d1;
d1.setname("test1");
Driver d2;
d2.setName("test2");
sample s(d1);
s.getDriver().display();
s.setDriver(d2);
s.getDriver().display();
}

C++ cannot access element of vector of abstract class?

I have 2 simple C++ headers implemented as in the following:
Attribute.h
#include <string>
using namespace std;
class IAttribute
{
virtual string getName(){};
};
class StringAttribute : public IAttribute
{
private:
string name = "";
string value = "";
public:
StringAttribute(string name, string value)
{
this->name = name;
this->value = value;
}
string getName()
{
return this->name;
}
string getStrValue()
{
return value;
}
void setValue(string value)
{
this->value = value;
}
};
tableRow.h
#include "attribute.h"
#include <vector>
using namespace std;
class TableRow
{
private:
vector<IAttribute *> attributeList;
int rowId;
public:
TableRow(int rowId)
{
this->rowId = rowId;
}
void addStrAttribute(string name, string value)
{
attributeList.push_back(new StringAttribute(name, value));
}
StringAttribute getStrAtt(string name)
{
for (int i = 0; i < (int)attributeList.size(); i++)
{
if (attributeList[i]->)//couldn't access the methods of StringAttributeImp
{
}
}
}
};
As in the comment of tableRow header above, I couldn't access the methods and properties of the Implementation class. What is wrong?
The getName function is private in the IAttribute class. So of course you're not able to access it.
You should change the getName function to public; or use friend class.

Stop Code instead of break with a Error Message

Here is some code that is from a great website which does what i want quite well (searching in a vector of class objects by addressing the class objects).
#include <iostream>
#include <vector>
#include <functional>
#include <algorithm>
using namespacestd;
class class1
{
private:
int id;
double value;
public:
class1(int i, double v) :id(i), value(v){ }
int getId()const { return id; }
double getValue() const { return value; }
};
class HasIdentifier :public unary_function<class1, bool>
{
public:
HasIdentifier(int id) : m_id(id) { }
bool operator()(const class1& c)const
{
return (c.getId() == m_id);
}
private:
int m_id;
};
class class2
{
private:
vector <class1> objects;
public:
class2()
{
objects.push_back(class1(1, 100.0));
objects.push_back(class1(2, 100.0));
objects.push_back(class1(3, 100.0));
}
double GetValueOfId(int id)
{
vector<class1>::iterator itElem = find_if(objects.begin(), objects.end(), HasIdentifier(id));
return itElem->getValue();
}
};
int main() {
class2 c;
int id = 4;
cout << id << " " << c.GetValueOfId(id);
cin.get();
return 0;
}
It works well but whenenver i put "int id ">3 it crashes because object only has the size 3. I got this, but is there a possibility to get warned when this will happen so that is does not crash but im able to correct it somehow in the code with a warn message?
You should check the returned iterator for validness and throw and exception (or report an error any other way) if it is invalid:
if (itElem == objects.end())
throw MyVeryCoolException("Woops wrong id");
Dont forget to set up a global exception handler (toplevel catch), otherwise your application will still crash if the exception is uncaught.