Related
Does it ever make sense to check if this is null?
Say I have a class with a method; inside that method, I check this == NULL, and if it is, return an error code.
If this is null, then that means the object is deleted. Is the method even able to return anything?
Update: I forgot to mention that the method can be called from multiple threads and it may cause the object to be deleted while another thread is inside the method.
Does it ever make sense to check for this==null? I found this while doing a code review.
In standard C++, it does not, because any call on a null pointer is already undefined behavior, so any code relying on such checks is non-standard (there's no guarantee that the check will even be executed).
Note that this holds true for non-virtual functions as well.
Some implementations permit this==0, however, and consequently libraries written specifically for those implementations will sometimes use it as a hack. A good example of such a pair is VC++ and MFC - I don't recall the exact code, but I distinctly remember seeing if (this == NULL) checks in MFC source code somewhere.
It may also be there as a debugging aid, because at some point in the past this code was hit with this==0 because of a mistake in the caller, so a check was inserted to catch future instances of that. An assert would make more sense for such things, though.
If this == null then that means the object is deleted.
No, it doesn't mean that. It means that a method was called on a null pointer, or on a reference obtained from a null pointer (though obtaining such a reference is already U.B.). This has nothing to do with delete, and does not require any objects of this type to have ever existed.
Your note about threads is worrisome. I'm pretty sure you have a race condition that can lead to a crash. If a thread deletes an object and zeros the pointer, another thread could make a call through that pointer between those two operations, leading to this being non-null and also not valid, resulting in a crash. Similarly, if a thread calls a method while another thread is in the middle of creating the object, you may also get a crash.
Short answer, you really need to use a mutex or something to synchonize access to this variable. You need to ensure that this is never null or you're going to have problems.
I know that this is old but I feel like now that we're dealing with C++11-17 somebody should mention lambdas. If you capture this into a lambda that is going to be called asynchronously at a later point in time, it is possible that your "this" object gets destroyed before that lambda is invoked.
i.e passing it as a callback to some time-expensive function that is run from a separate thread or just asynchronously in general
EDIT: Just to be clear, the question was "Does it ever make sense to check if this is null" I am merely offering a scenario where it does make sense that might become more prevalent with the wider use of modern C++.
Contrived example:
This code is completely runable. To see unsafe behavior just comment out the call to safe behavior and uncomment the unsafe behavior call.
#include <memory>
#include <functional>
#include <iostream>
#include <future>
class SomeAPI
{
public:
SomeAPI() = default;
void DoWork(std::function<void(int)> cb)
{
DoAsync(cb);
}
private:
void DoAsync(std::function<void(int)> cb)
{
std::cout << "SomeAPI about to do async work\n";
m_future = std::async(std::launch::async, [](auto cb)
{
std::cout << "Async thread sleeping 10 seconds (Doing work).\n";
std::this_thread::sleep_for(std::chrono::seconds{ 10 });
// Do a bunch of work and set a status indicating success or failure.
// Assume 0 is success.
int status = 0;
std::cout << "Executing callback.\n";
cb(status);
std::cout << "Callback Executed.\n";
}, cb);
};
std::future<void> m_future;
};
class SomeOtherClass
{
public:
void SetSuccess(int success) { m_success = success; }
private:
bool m_success = false;
};
class SomeClass : public std::enable_shared_from_this<SomeClass>
{
public:
SomeClass(SomeAPI* api)
: m_api(api)
{
}
void DoWorkUnsafe()
{
std::cout << "DoWorkUnsafe about to pass callback to async executer.\n";
// Call DoWork on the API.
// DoWork takes some time.
// When DoWork is finished, it calls the callback that we sent in.
m_api->DoWork([this](int status)
{
// Undefined behavior
m_value = 17;
// Crash
m_data->SetSuccess(true);
ReportSuccess();
});
}
void DoWorkSafe()
{
// Create a weak point from a shared pointer to this.
std::weak_ptr<SomeClass> this_ = shared_from_this();
std::cout << "DoWorkSafe about to pass callback to async executer.\n";
// Capture the weak pointer.
m_api->DoWork([this_](int status)
{
// Test the weak pointer.
if (auto sp = this_.lock())
{
std::cout << "Async work finished.\n";
// If its good, then we are still alive and safe to execute on this.
sp->m_value = 17;
sp->m_data->SetSuccess(true);
sp->ReportSuccess();
}
});
}
private:
void ReportSuccess()
{
// Tell everyone who cares that a thing has succeeded.
};
SomeAPI* m_api;
std::shared_ptr<SomeOtherClass> m_data = std::shared_ptr<SomeOtherClass>();
int m_value;
};
int main()
{
std::shared_ptr<SomeAPI> api = std::make_shared<SomeAPI>();
std::shared_ptr<SomeClass> someClass = std::make_shared<SomeClass>(api.get());
someClass->DoWorkSafe();
// Comment out the above line and uncomment the below line
// to see the unsafe behavior.
//someClass->DoWorkUnsafe();
std::cout << "Deleting someClass\n";
someClass.reset();
std::cout << "Main thread sleeping for 20 seconds.\n";
std::this_thread::sleep_for(std::chrono::seconds{ 20 });
return 0;
}
FWIW, I have used debugging checks for (this != NULL) in assertions before which have helped catch defective code. Not that the code would have necessarily gotten too far with out a crash, but on small embedded systems that don't have memory protection, the assertions actually helped.
On systems with memory protection, the OS will generally hit an access violation if called with a NULL this pointer, so there's less value in asserting this != NULL. However, see Pavel's comment for why it's not necessarily worthless on even protected systems.
Your method will most likely (may vary between compilers) be able to run and also be able to return a value. As long as it does not access any instance variables. If it tries this it will crash.
As others pointed out you can not use this test to see if an object has been deleted. Even if you could, it would not work, because the object may be deleted by another thread just after the test but before you execute the next line after the test. Use Thread synchronization instead.
If this is null there is a bug in your program, most likely in the design of your program.
I'd also add that it's usually better to avoid null or NULL. I think the standard is changing yet again here but for now 0 is really what you want to check for to be absolutely sure you're getting what you want.
This is just a pointer passed as the first argument to a function (which is exactly what makes it a method). So long as you're not talking about virtual methods and/or virtual inheritance, then yes, you can find yourself executing an instance method, with a null instance. As others said, you almost certainly won't get very far with that execution before problems arise, but robust coding should probably check for that situation, with an assert. At least, it makes sense when you suspect it could be occuring for some reason, but need to track down exactly which class / call stack it's occurring in.
I know this is a old question, however I thought I will share my experience with use of Lambda capture
#include <iostream>
#include <memory>
using std::unique_ptr;
using std::make_unique;
using std::cout;
using std::endl;
class foo {
public:
foo(int no) : no_(no) {
}
template <typename Lambda>
void lambda_func(Lambda&& l) {
cout << "No is " << no_ << endl;
l();
}
private:
int no_;
};
int main() {
auto f = std::make_unique<foo>(10);
f->lambda_func([f = std::move(f)] () mutable {
cout << "lambda ==> " << endl;
cout << "lambda <== " << endl;
});
return 0;
}
This code segment faults
$ g++ -std=c++14 uniqueptr.cpp
$ ./a.out
Segmentation fault (core dumped)
If I remove the std::cout statement from lambda_func The code runs to completion.
It seems like, this statement f->lambda_func([f = std::move(f)] () mutable { processes lambda captures before member function is invoked.
I want to build a helper class that can accept an std::function created via std::bind) so that i can call this class repeaded from another thread:
short example:
void loopme() {
std::cout << "yay";
}
main () {
LoopThread loop = { std::bind(&loopme) };
loop.start();
//wait 1 second
loop.stop();
//be happy about output
}
However, when calling stop() my current implementation will raise the following error: debug assertion Failed , see Image: i.stack.imgur.com/aR9hP.png.
Does anyone know why the error is thrown ?
I don't even use vectors in this example.
When i dont call loopme from within the thread but directly output to std::cout, no error is thrown.
Here the full implementation of my class:
class LoopThread {
public:
LoopThread(std::function<void(LoopThread*, uint32_t)> function) : function_{ function }, thread_{ nullptr }, is_running_{ false }, counter_{ 0 } {};
~LoopThread();
void start();
void stop();
bool isRunning() { return is_running_; };
private:
std::function<void(LoopThread*, uint32_t)> function_;
std::thread* thread_;
bool is_running_;
uint32_t counter_;
void executeLoop();
};
LoopThread::~LoopThread() {
if (isRunning()) {
stop();
}
}
void LoopThread::start() {
if (is_running_) {
throw std::runtime_error("Thread is already running");
}
if (thread_ != nullptr) {
throw std::runtime_error("Thread is not stopped yet");
}
is_running_ = true;
thread_ = new std::thread{ &LoopThread::executeLoop, this };
}
void LoopThread::stop() {
if (!is_running_) {
throw std::runtime_error("Thread is already stopped");
}
is_running_ = false;
thread_->detach();
}
void LoopThread::executeLoop() {
while (is_running_) {
function_(this, counter_);
++counter_;
}
if (!is_running_) {
std::cout << "end";
}
//delete thread_;
//thread_ = nullptr;
}
I used the following Googletest code for testing (however a simple main method containing the code should work):
void testfunction(pft::LoopThread*, uint32_t i) {
std::cout << i << ' ';
}
TEST(pfFiles, TestLoop)
{
pft::LoopThread loop{ std::bind(&testfunction, std::placeholders::_1, std::placeholders::_2) };
loop.start();
std::this_thread::sleep_for(std::chrono::milliseconds(500));
loop.stop();
std::this_thread::sleep_for(std::chrono::milliseconds(2500));
std::cout << "Why does this fail";
}
Your use of is_running_ is undefined behavior, because you write in one thread and read in another without a synchronization barrier.
Partly due to this, your stop() doesn't stop anything. Even without this UB (ie, you "fix" it by using an atomic), it just tries to say "oy, stop at some point", by the end it does not even attempt to guarantee the stop happened.
Your code calls new needlessly. There is no reason to use a std::thread* here.
Your code violates the rule of 5. You wrote a destructor, then neglected copy/move operations. It is ridiculously fragile.
As stop() does nothing of consequence to stop a thread, your thread with a pointer to this outlives your LoopThread object. LoopThread goes out of scope, destroying what the pointer your std::thread stores. The still running executeLoop invokes a std::function that has been destroyed, then increments a counter to invalid memory (possibly on the stack where another variable has been created).
Roughly, there is 1 fundamental error in using std threading in every 3-5 lines of your code (not counting interface declarations).
Beyond the technical errors, the design is wrong as well; using detach is almost always a horrible idea; unless you have a promise you make ready at thread exit and then wait on the completion of that promise somewhere, doing that and getting anything like a clean and dependable shutdown of your program is next to impossible.
As a guess, the vector error is because you are stomping all over stack memory and following nearly invalid pointers to find functions to execute. The test system either puts an array index in the spot you are trashing and then the debug vector catches that it is out of bounds, or a function pointer that half-makes sense for your std function execution to run, or somesuch.
Only communicate through synchronized data between threads. That means atomic data, or mutex guarded, unless you are getting ridiculously fancy. You don't understand threading enough to get fancy. You don't understand threading enough to copy someone who got fancy and properly use it. Don't get fancy.
Don't use new. Almost never, ever use new. Use make_shared or make_unique if you absolutely have to. But use those rarely.
Don't detach a thread. Period. Yes this means you might have to wait for it to finish a loop or somesuch. Deal with it, or write a thread manager that does the waiting at shutdown or somesuch.
Be extremely clear about what data is owned by what thread. Be extremely clear about when a thread is finished with data. Avoid using data shared between threads; communicate by passing values (or pointers to immutable shared data), and get information from std::futures back.
There are a number of hurdles in learning how to program. If you have gotten this far, you have passed a few. But you probably know people who learned along side of you that fell over at one of the earlier hurdles.
Sequence, that things happen one after another.
Flow control.
Subprocedures and functions.
Looping.
Recursion.
Pointers/references and dynamic vs automatic allocation.
Dynamic lifetime management.
Objects and Dynamic dispatch.
Complexity
Coordinate spaces
Message
Threading and Concurrency
Non-uniform address spaces, Serialization and Networking
Functional programming, meta functions, currying, partial application, Monads
This list is not complete.
The point is, each of these hurdles can cause you to crash and fail as a programmer, and getting each of these hurdles right is hard.
Threading is hard. Do it the easy way. Dynamic lifetime management is hard. Do it the easy way. In both cases, extremely smart people have mastered the "manual" way to do it, and the result is programs that exhibit random unpredictable/undefined behavior and crash a lot. Muddling through manual resource allocation and deallocation and multithreaded code can be made to work, but the result is usually someone whose small programs work accidentally (they work insofar as you fixed the bugs you noticed). And when you master it, initial mastery comes in the form of holding an entire program's "state" in uour head and understanding how it works; this fails to scale to large many-developer code bases, so younusually graduate to having large programs that work accidentally.
Both make_unique style and only-immutable-shared-data based threading are composible strategies. This means if small pieces are correct, and you put them together, the resulting program is correct (with regards to resource lifetime and concurrency). That permits local mastery of small-scale threading or resource management to apply to larfe-scale programs in the domain that these strategies work.
After following the guide from #Yakk i decided to restructure my programm:
bool is_running_ will change to td::atomic<bool> is_running_
stop() will not only trigger the stopping, but will activly wait for the thread to stop via a thread_->join()
all calls of new are replaced with std::make_unique<std::thread>( &LoopThread::executeLoop, this )
I have no experience with copy or move constructors. So i decided to forbid them. This should prevent me from accidently using this. If i sometime in the future will need those i have to take a deepter look on thoose
thread_->detach() was replaced by thread_->join() (see 2.)
This is the end of the list.
class LoopThread {
public:
LoopThread(std::function<void(LoopThread*, uint32_t)> function) : function_{ function }, is_running_{ false }, counter_{ 0 } {};
LoopThread(LoopThread &&) = delete;
LoopThread(const LoopThread &) = delete;
LoopThread& operator=(const LoopThread&) = delete;
LoopThread& operator=(LoopThread&&) = delete;
~LoopThread();
void start();
void stop();
bool isRunning() const { return is_running_; };
private:
std::function<void(LoopThread*, uint32_t)> function_;
std::unique_ptr<std::thread> thread_;
std::atomic<bool> is_running_;
uint32_t counter_;
void executeLoop();
};
LoopThread::~LoopThread() {
if (isRunning()) {
stop();
}
}
void LoopThread::start() {
if (is_running_) {
throw std::runtime_error("Thread is already running");
}
if (thread_ != nullptr) {
throw std::runtime_error("Thread is not stopped yet");
}
is_running_ = true;
thread_ = std::make_unique<std::thread>( &LoopThread::executeLoop, this );
}
void LoopThread::stop() {
if (!is_running_) {
throw std::runtime_error("Thread is already stopped");
}
is_running_ = false;
thread_->join();
thread_ = nullptr;
}
void LoopThread::executeLoop() {
while (is_running_) {
function_(this, counter_);
++counter_;
}
}
TEST(pfThread, TestLoop)
{
pft::LoopThread loop{ std::bind(&testFunction, std::placeholders::_1, std::placeholders::_2) };
loop.start();
std::this_thread::sleep_for(std::chrono::milliseconds(50));
loop.stop();
}
I am asking this question for general coding guidelines:
class A {
A() { ... throw 0; }
};
A obj; // <---global
int main()
{
}
If obj throws exception in above code then, it will eventually terminate the code before main() gets called. So my question is, what guideline I should take for such scenario ? Is it ok to declare global objects for such classes or not ? Should I always refrain myself from doing so, or is it a good tendency to catch the error in the beginning itself ?
If you NEED a global instance of an object whose constructor can throw, you could make the variable static, instead:
A * f(){
try {
//lock(mutex); -> as Praetorian points out
static A a;
//unlock(mutex);
return &a;
}
catch (...){
return NULL;
}
}
int main() {
A * a = f(); //f() can be called whenever you need to access the global
}
This would alleviate the problem caused by a premature exception.
EDIT: Of course, in this case the solution is 90% of the way to being a Singleton. Why not just fully turn it into one, by moving f() into A?
No, you should not declare such objects global - any exception will be unhandled and very hard to diagnose. The program will just crash which means that it will have very poor (below zero) user experience and will be rather hard to maintain.
As #Kerrek SB has mentioned in the comments, the answer to this is dependent on the reasons that can cause your class to throw. If you're trying to acquire a system resource that might be unavailable, I feel you shouldn't declare a global object. Your program will crash as soon as the user tries to run it; needless to say, that doesn't look very good. If it can throw a std::bad_alloc or some such exception that is unlikely under normal circumstances (assuming you're not trying to allocate a few GB of memory) you could make a global instance; however, I would still not do that.
Instead, you could declare a global pointer to the object, instantiate the object right at the beginning of main (before any threads have been spawned etc.) and point the pointer to this instance, then access it through the pointer. This gives your program a chance to handle exceptions, and maybe prompt the user to take some sort of remedial measures (like popping up a Retry button to try and reacquire the resource, for instance).
Declaring a global object is fine, but the design of your class is insignificant, it lacks details to be compatible with practical needs and use.
One solution no one seems to have mentionned is to use a function try
block. Basically, if the situation is that without the constructed
object, the rest of your program won't work or be able to do anything
useful, then the only real problem is that your user will get some sort
of incomprehensible error message if the constructor terminates with an
exception. So you wrap the constructor in a function try block, and
generate a comprehensible message, followed by an error return:
A::() try
: var1( initVar1 )
// ...
{
// Additional initialization code...
} catch ( std::exception const& ) {
std::cerr << "..." << std::endl;
exit(EXIT_FAILURE);
} catch (...) {
std::cerr << "Unknown error initializing A" << std::endl;
exit(EXIT_FAILURE);
}
This solution is really only appropriate, however, if all instances of
the object are declared statically, or if you can isolate a single
constructor for the static instances; for the non-static instances, it
is probably better to propagate the exception.
Like #J T have said, you can write like this:
struct S {
S() noexcept(false);
};
S &globalS() {
try {
static S s;
return s;
} catch (...) {
// Handle error, perhaps by logging it and gracefully terminating the application.
}
// Unreachable.
}
Such scenario is quite a problem, please read ERR58-CPP. Handle all exceptions thrown before main() begins executing for more detail.
I have an object on the stack for which I wish its destructor to skip some work when the destructor is being called because the stack is being unwound due to a specific exception being thrown through the scope of the object on the stack.
Now I could add a try catch block inside the scope of the stack item and catch the exception in question and notify the stack object to not run the work to be skipped an then rethrow the exception as follows:
RAII_Class pending;
try {
doSomeWorkThatMayThrowException();
} catch (exceptionToSkipPendingDtor &err) {
pending.notifySkipResourceRelease();
throw;
}
However, I'm hoping there is a more elegant way to do this. For example imagine:
RAII_Class::~RAII_Class {
if (detectExceptionToSkipPendingDtorBeingThrown()) {
return;
}
releaseResource();
}
You can almost do this with std::uncaught_exception(), but not quite.
Herb Sutter explains the "almost" better than I do: http://www.gotw.ca/gotw/047.htm
There are corner cases where std::uncaught_exception() returns true when called from a destructor but the object in question isn't actually being destroyed by the stack unwinding process.
You're probably better off without RAII because it doesn't match your use case. RAII means always clean up; exception or not.
What you want is much simpler: only release resource if an exception is not throw which is a simple sequence of functions.
explicitAllocateResource();
doSomeWorkThatMayThrowException();
explicitReleaseResource(); // skipped if an exception is thrown
// by the previous function.
I would do it the other way around - explicitly tell it to do its work if no exception was thrown:
RAII_Class pending;
doSomeWorkThatMayThrowException();
pending.commit(); // do or prepare actual work
This seems to circumvent the main reason to use RAII. The point of RAII is that if an exception happens in the middle of your code you can still release resources/be destructed properly.
If this isn;t the semantic you want, then don't use RAII.
So instead of:
void myFunction() {
WrapperClass wc(acquireResource());
// code that may throw
}
Just do:
void myFunction() {
Resource r = acquireResource();
// code that may throw
freeResource(r);
}
If the code in the middle throws, the resource won't be freed. This is what you want, rather than keeping RAII (and keeping the name) but not implementing RAII semantics.
Looks like bool std::uncaught_exception(); does the trick if you want to have this behavior for every exception, not just special ones!
You can do without a try-catch:
RAII_Class pending;
doSomeWorkThatMayThrowException(); // intentional: don't release if throw
pending.releaseResource();
Alternatively, you can try a little harder with RAII:
struct RAII_Class {
template<class Op>
void execute(Op op) {
op();
releaseResources();
}
private:
void releaseResources() { /* ... */ }
};
int main(int argc, char* argv[])
{
RAII_Class().execute(doSomeWorkThatMayThrowException);
return 0;
}
Although it would be a kludge at best, if you own the code for the exception class you're interested in, you could add a static data member to that class (bool) that would be set to "true" in the constructor for objects of that class, and false in the destructor (might need to be an int that you increment/decrement instead). Then in the destructor of your RAII class, you can check std::uncaught_exception(), and if true, query the static data member in your exception class. If you get true (or > 0) back, you've got one of those exceptions--otherwise you ignore it.
Not very elegant, but it would probably do the trick (as long as you don't have multiple threads).
I found this website with an interesting discussion about std::uncaught_exception() and an alternative solution to your question that seems much more elegant and correct to me:
http://www.gotw.ca/gotw/047.htm
// Alternative right solution
//
T::Close() {
// ... code that could throw ...
}
T::~T() /* throw() */ {
try {
Close();
} catch( ... ) {
}
}
In this way you're destructor does only one thing and you're protected against throwing an exception during an exception (which I assume is the problem you're trying to solve).
Does it ever make sense to check if this is null?
Say I have a class with a method; inside that method, I check this == NULL, and if it is, return an error code.
If this is null, then that means the object is deleted. Is the method even able to return anything?
Update: I forgot to mention that the method can be called from multiple threads and it may cause the object to be deleted while another thread is inside the method.
Does it ever make sense to check for this==null? I found this while doing a code review.
In standard C++, it does not, because any call on a null pointer is already undefined behavior, so any code relying on such checks is non-standard (there's no guarantee that the check will even be executed).
Note that this holds true for non-virtual functions as well.
Some implementations permit this==0, however, and consequently libraries written specifically for those implementations will sometimes use it as a hack. A good example of such a pair is VC++ and MFC - I don't recall the exact code, but I distinctly remember seeing if (this == NULL) checks in MFC source code somewhere.
It may also be there as a debugging aid, because at some point in the past this code was hit with this==0 because of a mistake in the caller, so a check was inserted to catch future instances of that. An assert would make more sense for such things, though.
If this == null then that means the object is deleted.
No, it doesn't mean that. It means that a method was called on a null pointer, or on a reference obtained from a null pointer (though obtaining such a reference is already U.B.). This has nothing to do with delete, and does not require any objects of this type to have ever existed.
Your note about threads is worrisome. I'm pretty sure you have a race condition that can lead to a crash. If a thread deletes an object and zeros the pointer, another thread could make a call through that pointer between those two operations, leading to this being non-null and also not valid, resulting in a crash. Similarly, if a thread calls a method while another thread is in the middle of creating the object, you may also get a crash.
Short answer, you really need to use a mutex or something to synchonize access to this variable. You need to ensure that this is never null or you're going to have problems.
I know that this is old but I feel like now that we're dealing with C++11-17 somebody should mention lambdas. If you capture this into a lambda that is going to be called asynchronously at a later point in time, it is possible that your "this" object gets destroyed before that lambda is invoked.
i.e passing it as a callback to some time-expensive function that is run from a separate thread or just asynchronously in general
EDIT: Just to be clear, the question was "Does it ever make sense to check if this is null" I am merely offering a scenario where it does make sense that might become more prevalent with the wider use of modern C++.
Contrived example:
This code is completely runable. To see unsafe behavior just comment out the call to safe behavior and uncomment the unsafe behavior call.
#include <memory>
#include <functional>
#include <iostream>
#include <future>
class SomeAPI
{
public:
SomeAPI() = default;
void DoWork(std::function<void(int)> cb)
{
DoAsync(cb);
}
private:
void DoAsync(std::function<void(int)> cb)
{
std::cout << "SomeAPI about to do async work\n";
m_future = std::async(std::launch::async, [](auto cb)
{
std::cout << "Async thread sleeping 10 seconds (Doing work).\n";
std::this_thread::sleep_for(std::chrono::seconds{ 10 });
// Do a bunch of work and set a status indicating success or failure.
// Assume 0 is success.
int status = 0;
std::cout << "Executing callback.\n";
cb(status);
std::cout << "Callback Executed.\n";
}, cb);
};
std::future<void> m_future;
};
class SomeOtherClass
{
public:
void SetSuccess(int success) { m_success = success; }
private:
bool m_success = false;
};
class SomeClass : public std::enable_shared_from_this<SomeClass>
{
public:
SomeClass(SomeAPI* api)
: m_api(api)
{
}
void DoWorkUnsafe()
{
std::cout << "DoWorkUnsafe about to pass callback to async executer.\n";
// Call DoWork on the API.
// DoWork takes some time.
// When DoWork is finished, it calls the callback that we sent in.
m_api->DoWork([this](int status)
{
// Undefined behavior
m_value = 17;
// Crash
m_data->SetSuccess(true);
ReportSuccess();
});
}
void DoWorkSafe()
{
// Create a weak point from a shared pointer to this.
std::weak_ptr<SomeClass> this_ = shared_from_this();
std::cout << "DoWorkSafe about to pass callback to async executer.\n";
// Capture the weak pointer.
m_api->DoWork([this_](int status)
{
// Test the weak pointer.
if (auto sp = this_.lock())
{
std::cout << "Async work finished.\n";
// If its good, then we are still alive and safe to execute on this.
sp->m_value = 17;
sp->m_data->SetSuccess(true);
sp->ReportSuccess();
}
});
}
private:
void ReportSuccess()
{
// Tell everyone who cares that a thing has succeeded.
};
SomeAPI* m_api;
std::shared_ptr<SomeOtherClass> m_data = std::shared_ptr<SomeOtherClass>();
int m_value;
};
int main()
{
std::shared_ptr<SomeAPI> api = std::make_shared<SomeAPI>();
std::shared_ptr<SomeClass> someClass = std::make_shared<SomeClass>(api.get());
someClass->DoWorkSafe();
// Comment out the above line and uncomment the below line
// to see the unsafe behavior.
//someClass->DoWorkUnsafe();
std::cout << "Deleting someClass\n";
someClass.reset();
std::cout << "Main thread sleeping for 20 seconds.\n";
std::this_thread::sleep_for(std::chrono::seconds{ 20 });
return 0;
}
FWIW, I have used debugging checks for (this != NULL) in assertions before which have helped catch defective code. Not that the code would have necessarily gotten too far with out a crash, but on small embedded systems that don't have memory protection, the assertions actually helped.
On systems with memory protection, the OS will generally hit an access violation if called with a NULL this pointer, so there's less value in asserting this != NULL. However, see Pavel's comment for why it's not necessarily worthless on even protected systems.
Your method will most likely (may vary between compilers) be able to run and also be able to return a value. As long as it does not access any instance variables. If it tries this it will crash.
As others pointed out you can not use this test to see if an object has been deleted. Even if you could, it would not work, because the object may be deleted by another thread just after the test but before you execute the next line after the test. Use Thread synchronization instead.
If this is null there is a bug in your program, most likely in the design of your program.
I'd also add that it's usually better to avoid null or NULL. I think the standard is changing yet again here but for now 0 is really what you want to check for to be absolutely sure you're getting what you want.
This is just a pointer passed as the first argument to a function (which is exactly what makes it a method). So long as you're not talking about virtual methods and/or virtual inheritance, then yes, you can find yourself executing an instance method, with a null instance. As others said, you almost certainly won't get very far with that execution before problems arise, but robust coding should probably check for that situation, with an assert. At least, it makes sense when you suspect it could be occuring for some reason, but need to track down exactly which class / call stack it's occurring in.
I know this is a old question, however I thought I will share my experience with use of Lambda capture
#include <iostream>
#include <memory>
using std::unique_ptr;
using std::make_unique;
using std::cout;
using std::endl;
class foo {
public:
foo(int no) : no_(no) {
}
template <typename Lambda>
void lambda_func(Lambda&& l) {
cout << "No is " << no_ << endl;
l();
}
private:
int no_;
};
int main() {
auto f = std::make_unique<foo>(10);
f->lambda_func([f = std::move(f)] () mutable {
cout << "lambda ==> " << endl;
cout << "lambda <== " << endl;
});
return 0;
}
This code segment faults
$ g++ -std=c++14 uniqueptr.cpp
$ ./a.out
Segmentation fault (core dumped)
If I remove the std::cout statement from lambda_func The code runs to completion.
It seems like, this statement f->lambda_func([f = std::move(f)] () mutable { processes lambda captures before member function is invoked.