I designed an App that holds a stack of layers and an active obj.
When a Layer is attached to the App, the Layer tells App what an active object is. But my design causes a sigtrap when deallocating.
It cause sigtrap because the destruction of shared_ptr<Obj> m_obj in App happens first which reduce the use_count to 1. Then the onDetech function gets call, setting the active shared_ptr<Obj> m_obj to nullptr and reduce use_count to 0! But the layer still holds an shared_ptr<Obj>.
The code below is a minimal example to reproduce. I notice my code has a reference cycle but I have no idea how to fix this except using a raw pointer for obj in the App class.
I used shared_ptr for obj in App because it makes sense to me that App has the shared ownership of obj. Should I not use shared_ptr in this case?
class App;
class Obj {
public:
~Obj() { std::cout << "obj destruct" << std::endl; }
};
class Layer {
public:
Layer() { m_obj = std::make_shared<Obj>(); }
~Layer() { std::cout << m_obj.use_count() << std::endl; }
void onAttach(App *app);
void onDetach();
std::shared_ptr<Obj> m_obj;
private:
App *m_app;
};
class LayerStack {
public:
void pushLayer(App *app, std::shared_ptr<Layer> layer) {
m_layers.push_back(layer);
layer->onAttach(app);
}
~LayerStack() {
for (auto &layer : m_layers) {
layer->onDetach();
}
}
private:
std::vector<std::shared_ptr<Layer>> m_layers;
};
class App {
public:
App() {
m_defaultLayer = std::make_shared<Layer>();
m_stack.pushLayer(this, m_defaultLayer);
}
~App() {}
LayerStack m_stack;
std::shared_ptr<Layer> m_defaultLayer;
std::shared_ptr<Obj> m_activeObj;
};
void Layer::onAttach(App *app) {
m_app = app;
app->m_activeObj = m_obj;
std::cout << m_obj.use_count() << std::endl;
}
void Layer::onDetach() {
m_app->m_activeObj = nullptr;
std::cout << m_obj.use_count() << std::endl;
}
int main() {
A a;
}
output:
2
obj destruct
-923414512
-923414512
You're accessing m_activeObj after its lifetime has ended, and thus the behavior of your program is undefined.
The sequence of events is as follows:
App object goes out of scope
~App runs
m_activeObj is destroyed; after this its lifetime has ended and it can no longer be accessed
m_defaultLayer is destroyed
m_stack is destroyed
m_layers[0].onDetach() is called
onDetach sets m_app->m_activeObj to nullptr, but its lifetime has already ended, so behavior is undefined.
Irrelevant other stuff; you're already screwed.
The solution is to reorder things so that you don't access m_activeObj after its lifetime has ended. Either move m_stack's declaration after m_activeObj so it gets destroyed first or clear it manually in ~App.
Related
I got a class which holds the application's logger as a unique_ptr. The logger can be set through a static function. Also, one can obviously log messages. I left out any thread synchronization (mutexes) to make things easier.
class LoggerWrapper {
public:
static void SetLogger(std::unique_ptr<logger::ILogger> new_logger);
static void Log(const std::string& message);
private:
static std::unique_ptr<logger::ILogger> logger_;
};
void LoggerWrapper::Log(const std::string& message) {
if (!logger_) {
// cannot log
} else {
logger_->OnLogEvent(message);
}
}
void LoggerWrapper::SetLogger(std::unique_ptr<logger::ILogger> new_logger) {
logger_ = std::move(new_logger);
}
My problem is: The unique_ptr gets destructed before some of the other classes inside the application. E.g. is the DTOR of Class Foo wants to log something, the unique_ptr might have already been destroyed (which is the case at the moment). This causes the ILogger implementation to be destroyed, resulting in no log output being possible.
Does anyone have an idea on how to easily fix this? I somehow need to "delay" the destruction of the static unique_ptr. I also tried changing it to a shared_ptr, but that only caused SIGABRTs with "pure virtual method called" errors.
Thanks in advance!
EDIT: Created a minimal working example which contradicts my experience. In this case, the static logger outlives the Foo class.
EDIT2: My application uses exit. That seems to change the order of destruction.
EDIT3: exit does not destroy local objects.
/******************************************************************************
Online C++ Compiler.
Code, Compile, Run and Debug C++ program online.
Write your code in this editor and press "Run" button to compile and execute it.
*******************************************************************************/
#include <iostream>
#include <memory>
#include <string>
using namespace std;
class ILogger {
public:
ILogger() {
std::cout << "ILogger CTOR" << std::endl;
}
~ILogger() {
std::cout << "ILogger DTOR" << std::endl;
}
virtual void OnLogEvent(const std::string& log_message) {
std::cout << "OnLogEvent: " << log_message << std::endl;
}
};
class LoggerWrapper {
public:
static void SetLogger(std::unique_ptr<ILogger> new_logger) {
logger_ = std::move(new_logger);
}
static void Log(const std::string& message) {
if (!logger_) {
// cannot log
} else {
logger_->OnLogEvent(message);
}
};
private:
static std::unique_ptr<ILogger> logger_;
};
class Foo {
public:
Foo(const std::string& name) : name_{name} {
LoggerWrapper::Log(name_ + ": CTOR");
}
~Foo() {
LoggerWrapper::Log(name_ + ": DTOR");
}
private:
std::string name_;
};
// declaring logger_ first causes it to be deleted AFTER foo
std::unique_ptr<ILogger> LoggerWrapper::logger_;
std::unique_ptr<Foo> foo;
int main()
{
LoggerWrapper::SetLogger(std::make_unique<ILogger>());
foo = std::make_unique<Foo>("Global FOO");
// local variables do NOT get destroyed when calling exit!
auto foo_local = Foo("Local FOO");
exit(1);
}
This is trivial.
First you don't use global static objects ( you should not be using global state like that). You use function static objects so you can control the order of creation/destruction.
So change this:
std::unique_ptr<ILogger> LoggerWrapper::logger_;
std::unique_ptr<Foo> foo;
Into:
class GlobalLogger
{
public:
ILogger& getLogger() {
static ILogger logger; // if you must use unique_ptr you can do that here
return logger; // But much simpler to use a normal object.
}
};
class GlobalFoo
{
public:
Foo& getFoo() {
// If there is a chance that foo is going to
// use global logger in its destructor
// then it should simply call `GlobalLogger::getLogger()`
// in the constructor of Foo. You then
// guarantee the order of creation and thus destruction.
// Alternatively, you can call it here in thus
// function just before the declaration of foo.
static Foo foo;
return foo;
}
};
// Where you were using `logger_` use `GlobalLogger::getLogger()`
// Where you were using `foo` use `GlobalFoo::getFoo()`
If we use your original code as the starting point we can do this:
#include <iostream>
#include <memory>
#include <string>
// Please don't do this.
// This is the number one worst practice.
// https://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice
using namespace std;
class ILogger {
public:
ILogger() {
std::cout << "ILogger CTOR" << std::endl;
}
~ILogger() {
std::cout << "ILogger DTOR" << std::endl;
}
virtual void OnLogEvent(const std::string& log_message) {
std::cout << "OnLogEvent: " << log_message << std::endl;
}
};
class LoggerWrapper
{
// Here store the logger
// as a static member of this private function.
// The the SetLogger() Log() functions get this reference.
static std::unique_ptr<ILogger>& getLogReference() {
static std::unique_ptr<ILogger> logger;
return logger;
}
public:
static void SetLogger(std::unique_ptr<ILogger> new_logger) {
// Save the new reference.
getLogReference() = std::move(new_logger);
}
// Use the logger if it has been set.
static void Log(const std::string& message) {
std::unique_ptr<ILogger>& logger_ = getLogReference();
if (!logger_) {
// cannot log
} else {
logger_->OnLogEvent(message);
}
};
};
class Foo {
public:
Foo(const std::string& name) : name_{name} {
// This calls Log()
// Which calls getLogReference()
// Which forces the creation of the function static
// variable logger so it is created before this
// object is fully initialized (if it has not already
// been created).
//
// This means this object was created after the logger
LoggerWrapper::Log(name_ + ": CTOR");
}
~Foo() {
// Because the Log() function was called in the
// constructor we know the loger was fully constructed first
// thus this object will be destroyed first
// so the logger object is guaranteed to be
// available in this objects destructor
// so it is safe to use.
LoggerWrapper::Log(name_ + ": DTOR");
}
private:
std::string name_;
};
std::unique_ptr<Foo>& globalFoo() {
// foo may destroy an object created later
// that has a destructor that calls LoggerWrapper::Log()
// So we need to call the Log function here before foo
// is created.
LoggerWrapper::Log("Initializing Global foo");
// Note: Unless somebody else has explicitly called SetLogger()
// the above line is unlikely to log anything as the logger
// will be null at this point.
static std::unique_ptr<Foo> foo;
return foo;
}
int main()
{
LoggerWrapper::SetLogger(std::make_unique<ILogger>());
globalFoo() = std::make_unique<Foo>("Global FOO");
// local variables do NOT get destroyed when calling exit!
auto foo_local = Foo("Local FOO");
exit(1);
}
The order in which static (global) objects are created and destroyed is undefined. This leave you a few options.
Don't use global objects, just raw use pointers which you can destroy yourself in the correct order.
Use a pointer to your logger that you never destroy. This technically is a memory leak but the kernel will cleanup when your application exits.
Use a shared_ptr for your logger. Each object that uses the logger gets a shared_ptr and the logger will be cleaned up after the last object is destroyed.
I am working on a multithreading program where a "std::deque< MyObject > myBuffer" is used as a FIFO buffer, a producer thread is constantly adding custom objects to the end of a deque using push_back(), and a consumer thread uses a helper function to retrieve the object and handle the synchronization and mutex.
std::deque< MyObject > myBuffer;
std::mutex mtx;
int main() {
std::thread producerThread(producer());
std::thread consumerThread(consumer());
// other code
return 0;
}
The producer function:
void producer() {
while (somecondition) {
// code producing MyObject object
std::lock_guard<std::mutex> lck(mtx);
myBuffer.push_back(object);
}
}
The consumer function:
void consumer() {
while(somecondition) {
MyObject object1, object2;
if (retrieve(object1)) {
// process object1
}
if (retrieve(object2)) {
// process object2
}
}
}
My current helper function looks like this:
bool retrieve(MyObject & object) {
// other code ...
std::lock_guard<std::mutex> lck(mtx);
if (!myBuffer.empty()) {
object = myBuffer.front();
myBuffer.pop_front();
return true;
} else {
return false;
}
}
However, I quickly realized that deque::front() returns the reference of the first element in the container. And "object" is MyObject&, so based on my understanding, only the reference of the first element in the deque is passed to object and as a result when I call the pop_front(), the element referenced should be gone and the object variable is holding an invalid reference. Surprisingly, when I actually ran the code, everything worked as opposed to what I expected. So could anyone help me understand how this "deque::front() returns the reference" works? Thanks.
It works properly and this is expected behavior.
You don't assign the reference - you can't, C++ references are immutable. You actually copy the value. This is how it is supposed to work. Semantic of foo = ... assignment when foo is a reference is roughly:
"copy the right-hand value to the place referenced by foo".
When there is a reference on the right side, the referenced value is copied.
In your case, object = myBuffer.front(); line copies the front value of deque to variable object1 or object2 in consumer(), respectively to the call. Later call to .pop_front() destroys the value in the deque, but doesn't affect the already copied value.
i can't understand you purpose,Maybe you can try deque::at()
pop_front() removes the first element from queue. It does not delete the object. So, referencing the object after pop_front() call should work.
Update -
#include <iostream>
#include <queue>
#include <algorithm>
class newClass {
public:
newClass () {
}
~newClass () {
std::cout << " Destructor is called. " << "\n";
}
newClass(const newClass &obj) {
std::cout << "Copy is called." << "\n";
}
void print(void) {
std::cout << "Hi there !" << "\n";
}
};
void queueWithPointer(void) {
std::deque<newClass *> deque;
deque.push_back(new newClass());
deque.push_front(new newClass());
newClass *b = deque.front();
std::cout << "pop_front starts" << "\n";
deque.pop_front();
std::cout << "pop_front ends" << "\n";
b->print();
}
void queueWithObjects(void) {
std::deque<newClass> deque;
deque.push_back(newClass());
deque.push_front(newClass());
newClass ba = deque.front();
std::cout << "pop_front starts" << "\n";
deque.pop_front();
std::cout << "pop_front ends" << "\n";
ba.print();
}
int main()
{
queueWithPointer();
// queueWithObjects();
return 0;
}
Above program can be used to understand the behaviour. In case of objects, copy constructor is called and a new copy is stored in deque. When pop_front() is called, the copy is deleted. While in case of pointers, address is copied. So, the address is deleted and not the actual object referenced by the address. You will find that destructor is not called in this case.
according to the code bellow, is myClass1 object and myClass2 obj (which is the myClass1 object's member ) moving to the new thread with their memory(Like std::move()) ?
class myClass1{
public:
myClass2 obj;
myClass1(myClass2 * obj) {
this.obj = *obj;
}
thread spawn() {
return std::thread([this] { this->Run(); });
}
void Run() {
cout << "new thread" << endl;
}
}
myClass2{
public :
string str;
MyClass2(string str){
this.str = str;
}
}
int main(){
myClass1 object(new myClass2("test"));
thread t = object.spawn();
t.join();
........
}
As it stands, your main will call std::terminate, because you discard a joinable std::thread.
If you join it, main will block until the thread has finished. object will remain alive for the entire duration of Run.
If you detach it, main may end before the thread does, object will cease to exist and the this in myClass1::Run will be invalid. Undefined Behaviour.
A tidy up of your code
class myClass1 {
myClass2 obj;
public:
// Take by rvalue, uses the move constructor for obj
myClass1(myClass2 && obj) : obj(obj) {}
std::thread spawn() {
return std::thread([this]
{
// This is suspicious, but safe
auto self = std::move(*this);
self.Run();
});
}
void Run() {
std::cout << "new thread" << std::endl;
}
}
int main(){
// new is not required
myClass1 object(myClass2("test"));
object.spawn().join();
/* other stuff, not involving object */
return 0;
}
Even more of a tidy up
class myClass1 {
myClass2 obj;
public:
// Take by rvalue, uses the move constructor for obj
myClass1(myClass2 && obj) : obj(obj) {}
void Run() {
std::cout << "new thread" << std::endl;
}
}
int main() {
// Just create the instance of myClass1 as a parameter to `std::thread`'s constructor
std::thread(&myClass1::Run, myClass1(myClass2("test"))).join();
/* other stuff */
return 0;
}
No; creating a thread does not magically make the thread take ownership of that memory. If you create an object on the stack, create a thread that uses it; and then unwind the stack, destroying the object; with the thread still running, you will have undefined behaviour.
If you want to give ownership of some data to the thread, the easiest way to do it is with a shared pointer.
I have a singleton with attributes which are pointers.
How do I prevent a memory leak when I no longer use it i.e. when the last reference to my instance is popped off the stack frame?
Does the destructor get called each time a reference gets poped off the stack?
A &A::getInstance()
{
static A instance; // does this get deleted at any point?
return instance;
}
Your singleton object will exist for the lifetime of the program and will be destroyed some time after main ends. At that point it's destructor will be invoked.
Here you may delete your raw pointers (or if using smart, you can set to nullptr or call reset).
This can be seen in action with the example below:
#include <iostream>
#include <string>
#include <memory>
class Foo
{
public:
Foo(std::string const& name = "Unknown")
: m_sName{ name }
{
std::cout << m_sName << " is created" << std::endl;
}
~Foo()
{
std::cout << m_sName << " is being destroyed" << std::endl;
}
std::string m_sName;
};
class Singleton
{
public:
static Singleton& Get()
{
static Singleton instance;
return instance;
}
~Singleton()
{
delete m_RawFoo;
m_SmartFoo = nullptr;
}
void print() const
{
std::cout << "Hello World" << std::endl;
}
protected:
private:
Singleton()
{
m_RawFoo = new Foo{ "Raw Foo" };
m_SmartFoo = std::make_shared<Foo>("Shared Foo");
}
Foo* m_RawFoo;
std::shared_ptr<Foo> m_SmartFoo;
};
int main()
{
std::cout << "Starting main..." << std::endl;
Singleton::Get().print();
Singleton::Get().print();
std::cout << "Ending main..." << std::endl;
return 0;
}
Which outputs the following:
Starting main...
Raw Foo is created
Shared Foo is created
Hello World
Hello World
Ending main...
Raw Foo is being destroyed
Shared Foo is being destroyed
I usually use shared_ptr and weak_ptr for singletons. The following is a singleton which is alive only while there are references to it. Note that this is not entirely thread-safe. If you want thread-safety, you'll need some additional logic (probably a lock) in GetInstance.
#include <memory>
class MySingleton
{
// singleton
public:
static std::shared_ptr<MySingleton> GetInstance();
private:
static std::weak_ptr<MySingleton> instance__;
// lifecycle
private:
MySingleton();
public:
~MySingleton();
// delete the copy constructor, move constructor, copy operator and move operator
private:
MySingleton(const MySingleton&) = delete;
MySingleton(MySingleton&&) = delete;
MySingleton& operator=(const MySingleton&) = delete;
MySingleton& operator=(MySingleton&&) = delete;
};
std::shared_ptr<MySingleton> MySingleton::GetInstance()
{
auto instance = instance__.lock();
if (!instance) {
instance.reset(new MySingleton);
instance__ = instance;
}
return instance;
}
std::weak_ptr<MySingleton> MySingleton::instance__;
MySingleton::MySingleton()
{
// initialization logic here
}
MySingleton::~MySingleton()
{
// clean-up logic here
}
Here's some sample client code:
int main()
{
// proper usage -- store the reference in a stack variable for the duration of its use
{
auto instance = MySingleton::GetInstance();
instance->doSomething();
instance->doSomethingElse();
// instance shared_ptr will be destructed automatically,
// which will then destruct the MySingleton instance
}
// BAD USAGE -- failing to store the reference will cause a new instance to be created and destroyed with each call
{
MySingleton::GetInstance()->doSomething();
MySingleton::GetInstance()->doSomethingElse();
}
// proper usage -- store the reference in a struct or class whose lifecycle is managed appropriately
{
// this class takes a shared reference and stores it
class Foo
{
public:
Foo(const std::shared_ptr<MySingleton>& dependency) : dependency_(dependency) { }
private:
std::shared_ptr<MySingleton> dependency_;
};
// this instance will store a shared reference
auto f = new Foo(MySingleton::GetInstance());
// when the destructor is invoked, the shared_ptr will be destructed,
// which will then destruct the MySingleton instance
delete f;
}
return 0;
}
How do I create a std::vector of objects, and each object has a boost::thread encapsulated inside.
class INSTRUMENT {
public:
INSTRUMENT() : m_thread(new boost::thread(&INSTRUMENT::Start, this)) {
x = "abc";
}
~INSTRUMENT() {}
void Start();
public:
std::string x;
boost::shared_ptr<boost::thread> m_thread;
};
void INSTRUMENT::Start() {
try {
while (1) {
boost::this_thread::interruption_point();
std::cout << "here " << x << std::endl;
}
} catch (boost::thread_interrupted &thread_e) {
std::cout << "exit " << x << std::endl;
} catch (std::exception &e) {
}
}
std::vector<INSTRUMENT> m_inst_vector;
for (int i = 0; i < 5; i++) {
m_inst_vector.push_back(INSTRUMENT());
}
The code compiles fine, but the output is just some garbage, not "abc" as expected. In debug, I notice that ~INSTRUMENT() is called every time when .push_back() is called.
I tried not to use boost::group_thread, because of the limitation on the current design. Just wondering whether it is possible to have a std::vector of objects with a thread inside, or any suggestion to a similar design would be very helpful.
I find a similar thread on SO. It mentioned about move-semantics supported in compiler, but didn't explain what it is.
How can I add boost threads to a vector
Thanks.
There are two problems with this code.
Firstly, the thread starts running immediately the boost::thread object is constructed, so you need to ensure that any data it accesses is initialized beforehand --- i.e. initialize x in the member initialization list prior to constructing the thread.
Secondly, the thread uses the this pointer of the INSTRUMENT object, so your object is tied to a specific address. std::vector copies values around: when you call push_back then it copies the object into the vector, and adding additional elements may copy the others around if a new memory block has to be allocated to make room. This is the cause of the destructor calls you see: the temporary is constructed, push_back copies it to the vector, and then the temporary is destructed.
To fix this, you need to ensure that once constructed your INSTRUMENT objects cannot be moved or copied, as copies have the wrong semantics. Do this by making your copy constructor and assignment operator private and unimplemented (or marking them deleted if you have a recent compiler that supports this new C++11 construct), or deriving from boost::noncopyable. Having done this then you no longer need a shared_ptr for the thread, as it cannot be shared, so you can just construct it directly.
If INSTRUMENT is not copyable, you can't store it directly in a vector, so use something like boost::shared_ptr<INSTRUMENT> in the vector. This will allow the vector to freely copy and reshuffle its elements, without affecting the address of the INSTRUMENT object, and ensuring that it is correctly destroyed at the end.
class INSTRUMENT: boost::noncopyable {
public:
INSTRUMENT() : x("abc"),m_thread(&INSTRUMENT::Start, this) {
}
~INSTRUMENT() {}
void Start();
public:
std::string x;
boost::thread m_thread;
};
void INSTRUMENT::Start() {
try {
while (1) {
boost::this_thread::interruption_point();
std::cout << "here " << x << std::endl;
}
} catch (boost::thread_interrupted &thread_e) {
std::cout << "exit " << x << std::endl;
} catch (std::exception &e) {
}
}
std::vector<boost::shared_ptr<INSTRUMENT> > m_inst_vector;
for (int i = 0; i < 5; i++) {
m_inst_vector.push_back(boost::shared_ptr<INSTRUMENT>(new INSTRUMENT));
}
EDIT: You have a race condition in your code. The thread starts before x gets initialized.
You should change the vector to vector<boost::shared_ptr<INSTRUMENT> >, and remove the boost::shared_ptr from inside INSTRUMENT.
class INSTRUMENT {
public:
INSTRUMENT() {
x = "abc";
m_thread = boost::thread(&INSTRUMENT::Start, this)
}
~INSTRUMENT() {}
void Start();
public:
std::string x;
boost::thread m_thread;
};
for (int i = 0; i < 5; i++) {
m_inst_vector.push_back(boost::shared_ptr<INSTRUMENT>(new INSTRUMENT()));
}