RPC client dangling reference fix (#34)

* Fix dangling reference
* Add docs for the dangling reference in lambda captures

Co-authored-by: Antonio Andelic <antonio.andelic@memgraph.io>
This commit is contained in:
antonio2368 2020-10-26 13:33:48 +01:00 committed by GitHub
parent 9b984ab2f2
commit f273be63a2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 32 additions and 4 deletions

View File

@ -29,6 +29,33 @@ You should use a pointer to `const` then. The primary reason being is that
references obscure the semantics of moving an object, thus making bugs with
references pointing to invalid memory harder to track down.
Example of this can be seen while capturing member variables by reference
inside a lambda.
Let's define a class that has two members, where one of those members is a
lambda that captures the other member by reference.
```cpp
struct S {
std::function<void()> foo;
int bar;
S() : foo([&]() { std::cout << bar; })
{}
};
```
What would happend if we move an instance of this object? Our lambda
reference capture will point to the same location as before, i.e. it
will point to the **old** memory location of `bar`. This means we have
a dangling reference in our code!
There are multiple ways to avoid this. The simple solutions would be
capturing by value or disabling move constructors/assignments.
Still, if we capture by reference an object that is not a member
of the struct containing the lambda, we can still have a dangling
reference if we move that object somewhere in our code and there is
nothing we can do to prevent that.
So, be careful with lambda catptures, and remember that references are
still a pointer under the hood!
[Style guide reference](https://google.github.io/styleguide/cppguide.html#Reference_Arguments)
#### Constructors & RAII

View File

@ -34,10 +34,11 @@ class Client {
res_load)
: self_(self),
guard_(std::move(guard)),
req_builder_([&](const uint8_t *data, size_t size, bool have_more) {
if (!self_->client_->Write(data, size, have_more))
throw RpcFailedException(self_->endpoint_);
}),
req_builder_(
[self](const uint8_t *data, size_t size, bool have_more) {
if (!self->client_->Write(data, size, have_more))
throw RpcFailedException(self->endpoint_);
}),
res_load_(res_load) {}
public: