提交 1dd82988 编写于 作者: S Sergey Zubkov

make CI happier

上级 ee28f500
...@@ -14918,58 +14918,56 @@ Coroutine rule summary: ...@@ -14918,58 +14918,56 @@ Coroutine rule summary:
### <a name="Rcoro-capture"></a>CP.51: Do not use capturing lambdas that are coroutines ### <a name="Rcoro-capture"></a>CP.51: Do not use capturing lambdas that are coroutines
##### Reason ##### Reason
Usage patterns that are correct with normal lambdas are hazardous with coroutine lambdas. The obvious pattern of capturing variables will result in accessing freed memory after the first suspension point, even for refcounted smart pointers and value types. Usage patterns that are correct with normal lambdas are hazardous with coroutine lambdas. The obvious pattern of capturing variables will result in accessing freed memory after the first suspension point, even for refcounted smart pointers and value types.
A lambda results in a closure object with storage, often on the stack, that will go out of scope at some point. When the closure object goes out of scope the captures will also go out of scope. Normal lambdas will have finished executing by this time so it is not a problem. Coroutine lambdas may resume from suspension after the closure object has destructed and at that point all captures will be use-after-free memory access. A lambda results in a closure object with storage, often on the stack, that will go out of scope at some point. When the closure object goes out of scope the captures will also go out of scope. Normal lambdas will have finished executing by this time so it is not a problem. Coroutine lambdas may resume from suspension after the closure object has destructed and at that point all captures will be use-after-free memory access.
##### Example, Bad ##### Example, Bad
```cpp
int value = get_value(); int value = get_value();
std::shared_ptr<Foo> sharedFoo = get_foo(); std::shared_ptr<Foo> sharedFoo = get_foo();
{ {
const auto lambda = [value, sharedFoo]() -> std::future<void> const auto lambda = [value, sharedFoo]() -> std::future<void>
{ {
co_await something(); co_await something();
// "sharedFoo" and "value" have already been destroyed // "sharedFoo" and "value" have already been destroyed
// the "shared" pointer didn't accomplish anything // the "shared" pointer didn't accomplish anything
}; };
lambda(); lambda();
} // the lambda closure object has now gone out of scope } // the lambda closure object has now gone out of scope
```
##### Example, Better ##### Example, Better
```cpp
int value = get_value(); int value = get_value();
std::shared_ptr<Foo> sharedFoo = get_foo(); std::shared_ptr<Foo> sharedFoo = get_foo();
{ {
const auto lambda = [](auto sharedFoo, auto value) -> std::future<void> // take as by-value parameter instead of as a capture // take as by-value parameter instead of as a capture
{ const auto lambda = [](auto sharedFoo, auto value) -> std::future<void>
co_await something(); {
// sharedFoo and value are still valid at this point co_await something();
}; // sharedFoo and value are still valid at this point
lambda(sharedFoo, value); };
} // the lambda closure object has now gone out of scope lambda(sharedFoo, value);
``` } // the lambda closure object has now gone out of scope
##### Example, Best ##### Example, Best
Use a function for coroutines. Use a function for coroutines.
```cpp std::future<void> Class::do_something(int value, std::shared_ptr<Foo> sharedFoo)
std::future<void> Class::do_something(int value, std::shared_ptr<Foo> sharedFoo) {
{ co_await something();
co_await something(); // sharedFoo and value are still valid at this point
// sharedFoo and value are still valid at this point }
}
void SomeOtherFunction()
void SomeOtherFunction() {
{ int value = get_value();
int value = get_value(); std::shared_ptr<Foo> sharedFoo = get_foo();
std::shared_ptr<Foo> sharedFoo = get_foo(); do_something(value, sharedFoo);
do_something(value, sharedFoo); }
}
```
##### Enforcement ##### Enforcement
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册