I want to use unique_ptr in a method. I want to rely on the fact that it is destroyed at the closing brace of the method (if that is indeed true).
The reason why I want to rely on this fact is that I want to write a simple class for logging that says when it has entered/exited a method, something like:
class MethodTracing
{
string _signature;
public:
MethodTracing(string signature)
{
_signature=signature;
BOOST_LOG_TRIVIAL(trace) << "ENTERED " << _signature ;
}
~MethodTracing()
{
BOOST_LOG_TRIVIAL(trace) << "EXITED " << _signature;
}
};
I can then use it like so:
void myMethod( )
{
auto _ = unique_ptr<MethodTracing>(new MethodTracing(__FUNCSIG__) ) ;
/// ...
}
Is it true (and consistent) that a unique_ptr, when created in a method, is destroyed at the end of the method (assuming it's not passed around).
Are there any other hidden (or otherwise!) pitfalls that I should be aware of?
Update:
As most of the answers suggested, I could have used local variable scoping. I tried this with MethodTracing(__FUNCSIG__);, but of course, I didn't assign a local variable! so it immediately went out of scope. I thought the runtime was being clever, but no, it was me being stupid (too long in C#!)
You don't need to do that - rely on automatic storage, e.g.
void myMethod( )
{
MethodTracing __sig(__FUNCSIG__);
// do stuff
}
__sig will be destroyed at the end of the function scope automatically
(yes __sig is bad form, call it something else if you want)
Yes, unique_ptr is destroyed at the end of the scope it's created in. However you don't need unique_ptr to get this functionality, because all C++ classes have this. You might as well just create your MethodTracing object directly:
void myMethod( )
{
MethodTracing _(__FUNCSIG__);
/// ...
}
You can usually rely on it. The exception would be code that explicitly calls terminate(). In general, destructors of objects are called when they go out of scope (for local variables, that is the end of the method). This is the foundation of RAII.
Yes that is true. But it is not necessarily when control flows through the closing brace. It can be because of a return, an exception or a goto out of its block.
However care should be taken when calling exit() to terminate the program. The local automatics like your unique ptr will no be destroyed then.
You ought to ensure that your ~MethodTracing destructor is no-throw if it is more complex that what you describe above, otherwise your class might only be partially destroyed.
Personally, I'd just declare it on the stack as mentioned above.
Related
I'm trying to implement the Observer pattern, but i don't want observers being responsible for my program safety by maintaining the reference list in ObservableSubject.
Meaning that when the Observer object lifetime ends, I dont want to explicitly call ObservervableSubject::removeObserver(&object).
I have come up with an idea to use use pointer references in ObservableSubject.
My question are: Is implementation described above and attempted below possible?
And what is happening in my program, how do i prevent dereferencing trash?
Apriori excuse: This is an attempt at understanding C++, not something that should have actual use or be prefered over other implementations.
My solution attempt:
// Example program
#include <iostream>
#include <string>
#include <vector>
class ObserverInterface {
public:
virtual ~ObserverInterface() {};
virtual void handleMessage() = 0;
};
class ObservableSubject
{
std::vector<std::reference_wrapper<ObserverInterface*>> listeners;
public:
void addObserver(ObserverInterface* obs)
{
if (&obs)
{
// is this a reference to the copied ptr?
// still, why doesnt my guard in notify protect me
this->listeners.push_back(obs);
}
}
void removeObserver(ObserverInterface* obs)
{
// todo
}
void notify()
{
for (ObserverInterface* listener : this->listeners)
{
if (listener)
{
listener->handleMessage();
}
}
}
};
class ConcreteObserver : public ObserverInterface {
void handleMessage()
{
std::cout << "ConcreteObserver: I'm doing work..." << std::endl;
}
};
int main()
{
ObservableSubject o;
{
ConcreteObserver c;
o.addListener(&c);
}
o.notify();
std::cin.get();
}
Line in ObservableSubject::notify() : Listener->handleMessage() throws the following exception:
Exception thrown: read access violation.
listener->**** was 0xD8BF48B. occurred
Your program has undefined behavior.
ObservableSubject o;
{
ConcreteObserver c;
o.addListener(&c); // Problem
}
c gets destructed when the scope ends. You end up storing a stale pointer in the list of listeners of o.
You can resolve the problem by defining c in the same scope as o or by using dynamically allocated memory.
ObservableSubject o;
ConcreteObserver c;
o.addListener(&c);
or
ObservableSubject o;
{
ConcreteObserver* c = new ConcreteObserver;
o.addListener(c);
}
When you use dynamically allocated memory, the additional scope is not useful. You might as well not use it.
ObservableSubject o;
ConcreteObserver* c = new ConcreteObserver;
o.addListener(c);
If you choose to use the second approach, make sure to deallocate the memory. You need to add
delete c;
before the end of the function.
Update, in response to OP's comment
You said:
Maybe i wasn't clear. Solving the lifetime/stale pointer problem was the intention of my solution. I know i have no problems if i have properly managed lifetime, or if i add detachObserver option on Observer destruction. I want to somehow be able to tell from the ObservableSubject if his list of Observers was corrupted, without the Observer explicitly telling that.
Since dereferencing an invalid pointer is cause for undefined behavior, it is essential that you track the lifetime of observers and make sure to update the list of observers when necessary. Without that, you are courting undefined behavior.
Note, I don't recommend the following approach, but I think it meets your requirements. You have a duplicated observer list. One is under control of the Observers, and the other, using weak pointers, is handled by the Observable object.
Make the Observer constructors private and use an ObserverFactory (which is their friend) to obtain a std::shared_ptr<Observer>. The factory has a map from raw pointers to reference wrappers to the associated shared pointer.
The listeners list becomes std::vector<std::weak_ptr<Observer>>. On list traversal, you try to lock the weak_ptr; if it succeeds, handle the message; if it fails, that is, you get nullptr, remove the weak pointer from the list.
When the listener no longer wants to listen, it tells the Factory to do a reset on its shared pointer and remove from the map. This step is rather ugly, as it is just a fancy delete this, normally a code smell.
I believe you can also do this with std::shared_from_this.
The plan is you move the maintenance away from the ObservableSubject back into the Observers.
// is this a reference to the copied ptr?
Yes, it is. It invokes undefined behaviour because the obs pointer variable goes out of scope at the end of the function, resulting in a dangling reference.
The whole idea doesn’t gain you anything. Even if you make the ref-to-pointer approach work correctly, you are depending on one thing: That that exact pointer variable is set to nullptr once the object dies. Essentially that’s the same problem as ensuring that no dangling pointers are held in listeners.
For a heap object: How do you make sure that nobody deletes the object through a different pointer? Or forgets to null the registered pointer? It’s even worse for stack objects like in your example. The object goes out of scope and dies automatically. There is no opportunity to null anything unless you introduce an additional pointer variable that you’d have to manage manually.
You could consider two general alternatives to your approach:
Make the relation bidirectional. Then whoever dies first (observable or observer) can notify the other party abouts its death in the destructor.
If you don’t like the bidirectionality a central, all-knowing orchestrator that decouples oberservers and observables works, too. Of course that introduces some kind of global state.
Real-life implementations usually go in the general direction of leveraging C++ destructors for deregistration. Have a look at Qt’s signal/slot mechanism, for example.
Given a situation where I want to have a stack allocated object that may throw during construction, but want to handle the exception at the calling site, how do I make the object accessible from outside the try block where it is constructed?
Eg
class MyThrowingClass {
MyThrowingClass() {throw exception();}
doSomethingImportant() {
//...
}
};
int main() {
//Need to catch the exception:
try {
MyThrowingClass myObj;
} catch() {
//actually handle the error
//...
}
//Also need to use myObj later on
myObj.doSomethingImportant();//but we can't use it here because it was scoped to the try block...
}
If I have myObj encased in a try then nothing outside the scope of the try can see it, but I don't want to have everything else inside there because then the code becomes 30 levels of nested try blocks, which is what the exception handling is supposed to remove with using the alternative of init function error codes.
I can't handle the exception inside the constructor as the reaction to the exception depends on the context of the use of MyThrowingClass.
Obviously the problem could be circumvented by having a
MyThrowingClass* pMyObj;
and then being able to wrapper the
pMyObj = new MyThrowingClass();
but surely this should be achievable with a stack allocated object too?
Is the only solution to do something like
MyThrowingClass myObj;
try {
myObj.init();
} catch(...) {
//...
}
at which point we're back to basically as bad as error codes and having an uninitialised or partially initialised object.
Note that this is not intended to be a global object, I want to have something that will be instantiated in many places.
Is it really the ideal solution to have a try block that wraps the entire scope (here everything that would be inside main) and catches that handle every possible exception at the end of that one try block as opposed to being able to handle exceptions vaguely near to their site?
int main() {
try {
//absoultely everything
}
catch (exceptionTypeA &a) {
//...
}
catch exceptionTypeB &b) {
}
}
how do I make the object accessible from outside the try block where it is constructed?
If construction fails, then the object doesn't exist; so there's nothing to access.
surely this should be achievable with a stack allocated object too?
Automatic (i.e. stack-allocated) objects are only initialised once, so even if you handle the exception, there's no way to go back and try to re-initialise it. If you do want to be able to retry, then you'll have to use something more complicated, like the dynamic allocation or two-stage initialisation you propose. Another alternative is something boost::optional (or, from next year, std::optional), which allows you to create and destroy objects at will within a lump of automatic storage.
Is it really the ideal solution to have a try block that wraps the entire scope?
In the typical case, where exceptions aren't handled locally and initialisation failure indicates an unrecoverable error, yes. In your special case, where you can handle it locally and recover, no.
try is designed to scope objects that can throw for a reason. By working around it, you are circumventing that which it's trying to protect you from (using a poorly defined object.) Consider using a function to generate the object. By using a noexcept move constructor, you can guarantee that the move out of the object is safe:
class MyThrowingClass {
public:
MyThrowingClass() {
throw exception();
}
// throw() is *okay* if you don't have noexcept
MyThrowingClass(const MyThrowingClass && other) noexcept {
}
};
MyThrowingClass GetObj() {
try {
return std::move(MyThrowingClass());
} catch(...) {
// return some well defined default or terminate program
}
}
int main() {
MyThrowingClass myObj(std::move(GetObj()));
}
Given a situation where I want to have a stack allocated object that may throw during construction, but want to handle the exception at the calling site, how do I make the object accessible from outside the try block where it is constructed?
Basically, you can't. As for wrapping ALL the code in a try block being a good or bad idea, that depends on the size of "all the code" - a dozen lines or so lines is no big deal.
Do you really want to call MyThrowingClass::doSomethingImportant() if the initialiser throws? Unless you somehow guarantee to fix the broken initialisation in the catch you're then calling methods on a partially initialised object.
Including the call to doSomethingImportant() in the same try block as the construction of the object would give you exactly what exceptions are designed to do: in the event of a problem skip past the following code (which is dependent on the preceding code) to an error handler.
This question already has answers here:
How can I determine if a C++ object has been deallocated?
(6 answers)
Closed 4 years ago.
Consider this program:
int main()
{
struct test
{
test() { cout << "Hello\n"; }
~test() { cout << "Goodbye\n"; }
void Speak() { cout << "I say!\n"; }
};
test* MyTest = new test;
delete MyTest;
MyTest->Speak();
system("pause");
}
I was expecting a crash, but instead this happened:
Hello
Goodbye
I say!
I'm guessing this is because when memory is marked as deallocated it isn't physically wiped, and since the code references it straight away the object is still to be found there, wholly intact. The more allocations made before calling Speak() the more likely a crash.
Whatever the reason, this is a problem for my actual, threaded code. Given the above, how can I reliably tell if another thread has deleted an object that the current one wants to access?
There is no platform-independent way of detecting this, without having the other thread(s) set the pointer to NULL after they've deleted the object, preferably inside a critical section, or equivalent.
The simple solution is: design your code so that this can't occur. Don't delete objects that might be needed by other threads. Clear up shared resource only once it's safe.
I was expecting a crash, but instead
this happened:
That is because Speak() is not accessing any members of the class. The compiler does not validate pointers for you, so it calls Speak() like any other function call, passing the (deleted) pointer as the hidden 'this' parameter. Since Speak() does not access that parameter for anything, there is no reason for it to crash.
I was expecting a crash, but instead this happened:
Undefined Behaviour means anything can happen.
Given the above, how can I reliably tell if another thread has deleted an object that the current one wants to access?
How about you set the MyTest pointer to zero (or NULL). That will make it clear to other threads that it's no longer valid. (of course if your other threads have their own pointers pointing to the same memory, well, you've designed things wrong. Don't go deleting memory that other threads may use.)
Also, you absolutely can't count on it working the way it has. That was lucky. Some systems will corrupt memory immediately upon deletion.
Despite it's best to improve the design to avoid access to a deleted object, you can add a debug feature to find the location where you access deleted objects.
Make all methods and the destructor virtual.
Check that your compiler creates an object layout where the pointer to
the vtable is in front of the object
Make the pointer to the vtable invalid in the destructor
This dirty trick causes that all functions calls reads the address where the pointer points to and cause a NULL pointer exception on most systems. Catch the exception in the debugger.
If you hesitate to make all methods virtual, you can also create an abstract base class and inherit from this class. This allows you to remove the virtual function with little effort. Only the destructor needs to be virtual inside the class.
example
struct Itest
{
virtual void Speak() = 0;
virtual void Listen() = 0;
};
struct test : public Itest
{
test() { cout << "Hello\n"; }
virtual ~test() {
cout << "Goodbye\n";
// as the last statement!
*(DWORD*)this = 0; // invalidate vtbl pointer
}
void Speak() { cout << "I say!\n"; }
void Listen() { cout << "I heard\n"; }
};
You might use reference counting in this situation. Any code that dereferences the pointer to the allocated object will increment the counter. When it's done, it decrements. At that time, iff the count hits zero, deletion occurs. As long as all users of the object follow the rules, nobody access the deallocated object.
For multithreading purposes I agree with other answer that it's best to follow design principles that don't lead to code 'hoping' for a condition to be true. From your original example, were you going to catch an exception as a way to tell if the object was deallocated? That is kind of relying on a side effect, even if it was a reliable side effect which it's not, which I only like to use as a last resort.
This is not a reliable way to "test" if something has been deleted elsewhere because you are invoking undefined behavior - that is, it may not throw an exception for you to catch.
Instead, use std::shared_ptr or boost::shared_ptr and count references. You can force a shared_ptr to delete it's contents using shared_ptr::reset(). Then you can check if it was deleted later using shared_ptr::use_count() == 0.
You could use some static and runtime analyzer like valgrind to help you see these things, but it has more to do with the structure of your code and how you use the language.
// Lock on MyTest Here.
test* tmp = MyTest;
MyTest = NULL;
delete tmp;
// Unlock MyTest Here.
if (MyTest != NULL)
MyTest->Speak();
One solution, not the most elegant...
Place mutexes around your list of objects; when you delete an object, mark it as null. When you use an object, check for null. Since access is serialized, you'll have a consistent operation.
I have code that controls a mutex lock/unlock based on scope:
void PerformLogin()
{
ScopeLock < Lock > LoginLock( &m_LoginLock );
doLoginCommand();
ScopeLock < SharedMemoryBase > MemoryLock( &m_SharedMemory );
doStoreLogin();
...
}
Can I guarantee that MemoryLock will be destructed before LoginLock?
Yes, it is. In any particular scope local objects are destroyed in the reverse order that they were constructed.
Yes, destructors are called in the reverse order of construction.
Adding on to Neil's answer.
Consider if the opposite was true, that is that you couldn't predict the order of destructors for stack declared variables. That would make it nearly impossible to use dependent value types on the stack. Consider
void Foo() {
Type1 t1;
Type2 t2(&t1);
...
}
If C++ did not guarantee destructor ordering, straight forward code like this would be incredibly unsafe because it would be possible for t1 to be destroyed before t2's destructor ran. Hence you could not guarantee t2's destructor ran with a valid t1 value.
The question was answered already, but I'd like to add that I typically have a habit of writing something like this:
void PerformLogin()
{
ScopeLock < Lock > LoginLock( &m_LoginLock );
doLoginCommand();
{
ScopeLock < SharedMemoryBase > MemoryLock( &m_SharedMemory );
doStoreLogin();
...
}
}
In my opinion, this makes the intent clearer (*). That might be relevant if your code really is relying on the specific order. I find that this makes it less likely that someone accidentally changes the order, and causes a hard-to-find bug. (Well, that is of course a non-issue, since we all have tests in place, don't we?)
I always write the redundant parentheses in something like (a && b) || c too, and I find this matter quite similar.
(*): Of course, you could use a comment as well.
Yes, destructors are the reverse of constructors. Because destructors are used to delete the objects which are no longer required and constructor are use to create the objects.
I have a case in which I have to read an input file in the C'tor, but sometimes this file doesn't exist.
This object is usually held statically, so its C'tor is called while loading the dll.
I can't catch the exception I throw if the file doesn't exist because it's too early, and my executable crashes in an ugly way.
I know it's bad practice to throw exceptions out of a C'tor, but I can't go on if the file doesn't exist, so I have to.
Is there a way to catch the exception while loading the dll, and if not, is there any better solution for this scenario?
Thanks,
Gal
I assume the static object has the file scope (it is outside any function/class definition). You may consider moving it to an accessor function and accessing it only via that function, like this:
class Object;
Object& getObject()
{
static Object object;
return object;
}
The static instance of Object will be initialized upon the first calling of the getObject() method. If the Object's constructor throws, you can easily catch the exception. Just you need to remember wrapping every call of getObject() into a try/catch block (or suffer from the exception bubbling up the stack chain); that may be a bit inconvenient, but on the other hand you may decide to wrap just the logically "first" call, if you know which one it is in the program logic flow.
Throwing exceptions out of a constructor is not necessarily a bad practice. In fact, RAII usually requires you to do this sort of things, because objects have an internal invariant that must be satisfied, and if the constructor can't initialize the object and leave it in a valid state, then it's the only way to go.
Throwing exceptions from a destructor, on the other hand, is a bad practice (and also a dangerous one). But throwing them from a constructor should be OK.
If you can use c++11 then there is a lambda and unique_ptr<> solution to this:
// In some_file.hpp
#pragma once
#include <memory>
#include <stdexcept>
class CtorThrows {
public:
CtorThrows (int value) {
if (value < 10) {
throw std::runtime_error("oops!");
}
}
};
class ClassWithStatic {
public:
private:
static std::unique_ptr<CtorThrows> bad_member_; // <-- static member
};
and then
// In some_file.cpp
#include "some_file.hpp"
// Create a lambda function to initialize the static member variable.
std::unique_ptr<CtorThrows> ClassWithStatic::bad_member_ = []() {
try {
int value = 5; // in this case, it is a bad value
// This only returns successfully if bad_value DOESN'T cause
// the ctor to throw and exception.
return std::make_unique<CtorThrows>(value);
} catch (std::runtime_error &e) {
std::cerr << "OOPs! Here's a nice error message" << std::endl;
exit(1);
}
return std::unique_ptr<CtorThrows>(nullptr);
}();
Using a unique_ptr lets you do this even with classes with that have a deleted or private copy constructor and copy assignment operator.
Redesign the object in such a way that it opens the file later - for example when the data from the file is requested the first time.
Alternatively replase the static object with a static pointer and call new when needed. It's better to use a smart pointer like auto_ptr.
How about separating reading the input file from the Constructor? You could have a separate Init() Method that must be called after constructing the object but before the object is actually ready to use.
You're right that you can't catch exeptions that happen during the initialization of static objects.
Since you're writing a DLL: Each DLL can have an entry-point, and inside this entry point exception handling works. (It's the same as main in your main-program). I'd remove the static instances of your classes, replace them with pointers and initialize these pointers inside dllmain.
That'll solve your problems once for all.
Btw - the DLL entrypoint gets called on load, unload and other events such as process attach/detach ect. Be sure you use the correct place to initialize your classes.
One way may be to "design" this to make the calling code (i.e. the code outside the dll) responsible for making sure all dependencies of the dll is in place. A function in the calling code that makes sure the dll's dependencies, in this case the file, is in place and is loadable before loading the library. If not, it can gracefully exit.