The following code illustrates my intent: https://godbolt.org/z/dhhascnoo
#include<string>
#include<sstream>
#include<iomanip>
#include<iostream>
#include<memory>
class Dbg
{
protected:
bool enabled;
public:
Dbg() : enabled(false) {}
Dbg(bool enable) : enabled(enable) {}
void print()
{
if (enabled) {
std::cout << "Debugging!" << std::endl;
}
}
};
class C1
{
protected:
std::shared_ptr<Dbg> dbg;
public:
C1() { dbg = std::make_shared<Dbg>(false); }
C1(std::shared_ptr<Dbg> dbg) : dbg(dbg) {}
void print()
{
dbg->print();
}
};
class C0
{
protected:
std::shared_ptr<Dbg> dbg;
C1 c1Inst;
public:
C0() : c1Inst(dbg) { dbg = std::make_shared<Dbg>(false); }
C0(std::shared_ptr<Dbg> dbg) : dbg(dbg) {}
void run()
{
c1Inst.print();
}
};
int main()
{
std::shared_ptr<Dbg> dbg = std::make_shared<Dbg>(true);
C0 c0Inst;
c0Inst.run();
}
Basically, I have some utility class that I want to pass to most of my objects that I run. With the ability to print out log messages (with configurable files to log them to).
I intend to pass a shared_ptr of this utility object to all of my subclasses. However, something about how I'm initiating the constructors to these classes seems to be off and causing a segfault.
I'm not as intimately knowledgeable about constructor design, so maybe someone can spot my mistake here?
EDIT: I realized my mistake here was not passing the actual pointer of dbg
in main (doh!). It should be:
int main()
{
std::shared_ptr<Dbg> dbg = std::make_shared<Dbg>(true);
C0 c0Inst(dbg);
c0Inst.run();
}
Still, the default constructor of C0
should've created a new Dbg object to reference, no?
CodePudding user response:
Your code has undefined behavior due to calling the unitized std::shared_ptr<Dbg>
.
In class C0
, you have not initialized the member C1 c1Inst;
in its default constructor (i.e. C0():...
) . Then you are calling the run()
from the class
void run() {
c1Inst.print();
}
Which will run the print
from the C1
where you have not initialized again the std::shared_ptr<Dbg> dbg;
. This is undefined behavior.
In order to fix, you need simply the the constrictors of the C0
be
C0()
: dbg{ std::make_shared<Dbg>(false) }
, c1Inst{ dbg }
{}
C0(std::shared_ptr<Dbg> dbg)
: dbg(dbg)
, c1Inst{ dbg }
{}
So-that all the members of the class will be initialized properly before using it. Here is a demo
CodePudding user response:
As it was said, you pass nullptr to C1, as initializer lists get called before constructor:
C0(): c1Inst(dbg) {dbg=std::...
so you basically not initialized pointer for C1.
To solve it, you should initialize a pointer first, so for example change default constructor to:
C0()
{
dbg = std::make_shared<Dbg>(false);
c1Inst = C1(dbg);
}