-
Notifications
You must be signed in to change notification settings - Fork 148
Common mistakes
These are common mistakes that you can make while writing lambda expression for libuv.
When you pass objects into the callback function body as reference([&]):
{
tcp server;
server.listen([&](/*...*/) {
// callback body #1
}
}
server object is not available in the callback body #1, because it went out of scope. Even if you make server variable a pointer, you have still out-of-scope problem.
{
auto server = new tcp;
server->listen([&](/*...*/) {
// callback body #1
}
}
Because, passed object into the callback function is the pointer variable itself, not a pointee. This also means that above code fails to delete server variable.
What about passing by value([=]):
{
tcp server;
server.listen([=](/*...*/) {
// callback body #1
}
}
In case you object type (tcp in above code) support copying appropriately, this code is okay. But, if you pass by value pointer variables:
{
auto server = new tcp;
server->listen([=](/*...*/) {
// callback body #1
// ...
delete server; // MUST DELETE
}
}
In this case, you are responsible for deleting the pointer in the callback function body (before you lost it).
I didn't test many compilers, but, at least gcc compiler has this problem.
Look at this code:
{
shared_ptr<tcp> server(new tcp);
server->listen([=](/*...*/) {
// callback body #1
// ...
// delete server;
}
}
For some reason, you decided to use shared_ptr. As you expected, server is deleted after the callback function ends, meaning that you don't have to delete it manually. And, this is true because we passed it by value, not by reference. If you used [&] instead, server was to deleted before the callback called.
There are another problem when you use smart pointer. If you didn't use server variable inside the callback function, compiler won't copy server variable for the callback. That's the problem because, in that case, server variable will be deleted immediately (before the callback invoked). For example:
template<typename F>
void tcp::listen(F callback) {
// ...
tcp* save_this_to_pass_to_callback = this;
// ...
}
In this code, this pointer was stored to be used later. Right after listen() function returns, server will be deleted and save_to_pass_to_callback is invalid object now.