From 1dd82988d7c15a169fa20c215374c7434c42c4cb Mon Sep 17 00:00:00 2001 From: Sergey Zubkov Date: Thu, 11 Mar 2021 15:21:49 -0500 Subject: [PATCH] make CI happier --- CppCoreGuidelines.md | 76 +++++++++++++++++++++----------------------- 1 file changed, 37 insertions(+), 39 deletions(-) diff --git a/CppCoreGuidelines.md b/CppCoreGuidelines.md index e85fc56..4ada92e 100644 --- a/CppCoreGuidelines.md +++ b/CppCoreGuidelines.md @@ -14918,58 +14918,56 @@ Coroutine rule summary: ### CP.51: Do not use capturing lambdas that are coroutines - ##### 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. 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 -```cpp -int value = get_value(); -std::shared_ptr sharedFoo = get_foo(); -{ - const auto lambda = [value, sharedFoo]() -> std::future - { - co_await something(); - // "sharedFoo" and "value" have already been destroyed - // the "shared" pointer didn't accomplish anything - }; - lambda(); -} // the lambda closure object has now gone out of scope -``` + + int value = get_value(); + std::shared_ptr sharedFoo = get_foo(); + { + const auto lambda = [value, sharedFoo]() -> std::future + { + co_await something(); + // "sharedFoo" and "value" have already been destroyed + // the "shared" pointer didn't accomplish anything + }; + lambda(); + } // the lambda closure object has now gone out of scope ##### Example, Better -```cpp -int value = get_value(); -std::shared_ptr sharedFoo = get_foo(); -{ - const auto lambda = [](auto sharedFoo, auto value) -> std::future // take as by-value parameter instead of as a capture - { - 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 -``` + + int value = get_value(); + std::shared_ptr sharedFoo = get_foo(); + { + // take as by-value parameter instead of as a capture + const auto lambda = [](auto sharedFoo, auto value) -> std::future + { + 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 ##### Example, Best + Use a function for coroutines. -```cpp -std::future Class::do_something(int value, std::shared_ptr sharedFoo) -{ - co_await something(); - // sharedFoo and value are still valid at this point -} + std::future Class::do_something(int value, std::shared_ptr sharedFoo) + { + co_await something(); + // sharedFoo and value are still valid at this point + } -void SomeOtherFunction() -{ - int value = get_value(); - std::shared_ptr sharedFoo = get_foo(); - do_something(value, sharedFoo); -} -``` + void SomeOtherFunction() + { + int value = get_value(); + std::shared_ptr sharedFoo = get_foo(); + do_something(value, sharedFoo); + } ##### Enforcement