小编Dav*_*ger的帖子

无栈C ++ 20协程是否有问题?

基于以下内容,C ++ 20中的协程看起来像是无堆栈的。

https://en.cppreference.com/w/cpp/language/coroutines

我担心的原因有很多:

  1. 在嵌入式系统上,堆分配通常是不可接受的。
  2. 在低级代码中,co_await的嵌套很有用(我不相信无栈协程允许这样做)。

使用无堆栈协程时,只有顶层例程可以被挂起。该顶级例程调用的任何例程本身都不会暂停。这禁止在通用库中的例程中提供挂起/恢复操作。

https://www.boost.org/doc/libs/1_57_0/libs/coroutine/doc/html/coroutine/intro.html#coroutine.intro.stackfulness

  1. 由于需要自定义分配器和内存池,因此代码更加详细。

  2. 如果任务等待操作系统为它分配一些内存(没有内存池),则速度较慢。

鉴于这些原因,我真的希望我对当前的协程是错误的。

问题分为三个部分:

  1. 为什么C ++选择使用无堆栈协程?
  2. 关于在无堆栈协程中保存状态的分配。我可以使用alloca()避免通常用于协程创建的任何堆分配。

协程状态是通过非数组运算符new在堆上分配的。 https://en.cppreference.com/w/cpp/language/coroutines

  1. 我对C ++协程的假设是错误的,为什么?

编辑:

我现在正在为协程进行cppcon讨论,如果我对自己的问题有任何答案,我将其发布(到目前为止没有任何内容)。

CppCon 2014:Gor Nishanov“等待2.0:无堆栈可恢复函数”

https://www.youtube.com/watch?v=KUhSjfSbINE

CppCon 2016:James McNellis“ C ++协程简介”

https://www.youtube.com/watch?v=ZTqHjjm86Bw

c++ asynchronous c++20 c++-coroutine

56
推荐指数
3
解决办法
5069
查看次数

C++20 协程,await_resume、return_value 和 yield_value 的意外重新排序

背景

我有个任务类型既可以co_returnco_yield。在 LLVM 中,任务按预期工作并通过了一些早期测试。在 MSVC 和 GCC 中,代码以相同的方式失败(巧合?)。


简要问题

具有以下测试功能:

Task<int> test_yielding()
{
    co_yield 1;
    co_return 2;
}
Run Code Online (Sandbox Code Playgroud)

从 Task 对象中检索了两个值。

auto a = co_await fn;
auto b = co_await fn;
Run Code Online (Sandbox Code Playgroud)

a 的值预期为 1,b 的值预期为 2。

结果针对 进行测试a + b == 3

上面的测试通过了,但是下面的测试失败了:

auto res = co_await fn + co_await fn
Run Code Online (Sandbox Code Playgroud)

GCC 和 MSVC 的 res 值为 4。两者都是从最终的 co_return 中检索到的。据我了解,第一次和第二次调用的co_await fn顺序应该是 1 和 2。

在 MSVC 和 GCC 中,代码失败,因为它们似乎重新排序await_resumereturn_value …

c++ c++20 c++-coroutine

21
推荐指数
1
解决办法
642
查看次数

未记载的链接器问题:"ld返回253退出状态"

什么

我收到一条错误消息,我找不到任何信息,是否有人知道我在哪里可以找到有关ld 253退出状态的任何信息?我什么都找不到.谷歌只有一个提及,它看似无关,没有解决方案.

size

对于链接器和编译器的详细输出,没有其他警告或错误甚至模糊地与上述相关.

试图找到问题

该错误在某种程度上与程序大小有关,但程序尚未达到系统闪存大小,所以我有点困惑.

如果我运行大小,则结果如下(设备限制为64K):

text    data     bss     dec
45608     396    6200   52204
Run Code Online (Sandbox Code Playgroud)

当我将设备内存大小增加到128K时没有任何变化,相同的消息......但是,如果我将代码大小减少到大约54 K以下程序编译,我删除哪个代码无关紧要.

如果我只添加一点代码,二进制文件的大小应该只增加几百个字节.但是,当我这样做时,链接器失败并出现上述错误.

在检查从objcopy创建的二进制文件时,内存中有一个巨大的空白区域,内存肯定不是满的.链接器文件已附加但我不知道它们是如何导致我的问题的:

删除链接以支持在问题中包含链接器文件.

更新

问题仍然存在,但我注意到在生成的映射文件中它似乎停在一个模板对象的中间,就好像链接器只是抛出一些异常并中止.它停在的行是相当繁重的模板代码,但它确实实例化它崩溃的确切事物(或者至少类似的对象,唯一的区别是捕获的lambda类型,它们总是按照标准的唯一类型).

映射文件中的最后一项是0x080008ce,并且因为闪存从地址0x08000000开始,这实际上是0x08ce,这远远不及闪存的末尾.

sections.ld

/*
 * Default linker script for Cortex-M (it includes specifics for STM32F[34]xx).
 *
 * To make use of the multi-region initialisations, define
 * OS_INCLUDE_STARTUP_INIT_MULTIPLE_RAM_SECTIONS for the _startup.c file.
 */

/*
 * The '__stack' definition is required by crt0, do not remove it.
 */
__stack = ORIGIN(RAM) + LENGTH(RAM);

_estack = __stack;     /* STM specific definition …
Run Code Online (Sandbox Code Playgroud)

c++ ld

8
推荐指数
1
解决办法
339
查看次数

使用 CMake 和嵌入式目标进行 clang-tidy

这里的目标是帮助人们在使用 C++ 进行开发时捕获嵌入式系统上的一些错误。作为其中的一部分,我试图让 clang-tidy 适合小型嵌入式目标。

我正在尝试设置 CMake 来执行以下操作:

  1. 在构建时运行 clang 整洁;然后
  2. 使用 GCC 8.2 编译

但是,clang-tidy 失败并显示“未知目标 CPU 'armv6-m”

--

我使用的CMake脚本如下:

ClangTidy.cmake

set(ENABLE_CLANG_TIDY ON CACHE BOOL "Add clang-tidy automatically to builds")
if (ENABLE_CLANG_TIDY)
    find_program(CLANG_TIDY_EXE NAMES "C:\\Program Files\\LLVM\\bin\\clang-tidy.exe")
    if (CLANG_TIDY_EXE)
        message(STATUS "clang-tidy found: ${CLANG_TIDY_EXE}")
        set(CLANG_TIDY_CHECKS "-*,modernize-*")
        set(CMAKE_CXX_CLANG_TIDY "${CLANG_TIDY_EXE};-checks=${CLANG_TIDY_CHECKS};-header-filter='${CMAKE_SOURCE_DIR}/*'"
        CACHE STRING "" FORCE)
    else()
        message(AUTHOR_WARNING "clang-tidy not found!")
        set(CMAKE_CXX_CLANG_TIDY "" CACHE STRING "" FORCE) # delete it
    endif()
endif()
Run Code Online (Sandbox Code Playgroud)

armv6-m 是 CMake 脚本的一部分,但它仅用于 GCC,并使用以下命令来设置 GCC 标志:

set(TARGET STM32F070x6)
set(ARCH armv6-m)
set(CORE cortex-m0) …
Run Code Online (Sandbox Code Playgroud)

c++ embedded cmake clang-tidy

7
推荐指数
1
解决办法
3371
查看次数

MSVC 不良装配生成

比较 MSVC、clang 和 GCC 中生成的程序集时。MSVC 程序集似乎比 Clang 代码差得多。


问题

GCC 和 MSVC 中是否有一个必需的标志来生成等效的程序集,或者在这种特定情况下 Clang 更好。我尝试了各种 MSVC 标志(不同的 /O 标志),但没有发生实质性变化。

或者我的代码是否有变化,可以让编译器实现更好的优化。我尝试过改变代码而不丢失基本结构也没有改变。


代码

我正在编译的代码只有 26 行,所以这里是:

#include <cstdint>
#include <type_traits>

template <typename A, typename B>
struct BitCast
{
    static_assert(std::is_pod<A>(), "BitCast<A, B> : A must be plain old data type.");
    static_assert(std::is_pod<B>(), "BitCast<A, B> : B must be plain old data type.");
    static_assert(sizeof(A) == sizeof(B), "BitCast<A, B> : A and B must be the same size.");
    static_assert(alignof(A) == alignof(B), "BitCast<A, B> : A and …
Run Code Online (Sandbox Code Playgroud)

c++ assembly gcc clang visual-c++

5
推荐指数
0
解决办法
313
查看次数

C++20 协程使用 Final_suspend 进行延续

背景

\n\n

在确信C++ 无堆栈协程非常棒之后。我一直在为我的代码库实现协程,并意识到 Final_Suspend 中的一个奇怪之处。

\n\n

语境

\n\n

让\xe2\x80\x99s 假设你有以下final_suspend函数:

\n\n
final_awaitable final_suspend() noexcept\n{\n    return {};\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

并且,final_awaitable的实现如下:

\n\n
struct final_awaitable\n{\n    bool await_ready() const noexcept\n    {\n        return false;\n    }\n    default_handle_t await_suspend( promise_handle_t h ) const noexcept\n    { \n        return h.promise().continuation();\n    }\n    void await_resume() const noexcept {}\n};\n
Run Code Online (Sandbox Code Playgroud)\n\n

如果这里的延续是从任务队列中原子检索的,并且任务队列可能为空(这可能发生在await_readyawait_suspend之间的任何时间),那么await_suspend必须能够返回一个空白延续。

\n\n

据我了解,当await_suspend返回句柄时,返回的句柄立即恢复(N4775草案中的5.1)。因此,如果此处没有可用的延续,则任何应用程序都会崩溃,因为在从wait_suspend接收到无效的协程句柄后,会在无效的协程句柄上调用恢复。

\n\n

以下是执行顺序:

\n\n
final_suspend                        Constructs final_awaitable.\n    final_awaitable::await_ready     Returns false, …
Run Code Online (Sandbox Code Playgroud)

c++ continuations c++20 c++-coroutine

3
推荐指数
1
解决办法
1218
查看次数

C++ 导入关键字、模块关键字和导出关键字

介绍

在C++标准草案中:

其中提到了这些术语import-keywordmodule-keywordexport-keyword

困惑

在语法部分,我不太确定按照A.1 概述如何可能

“此处描述的语法接受有效 C++ 结构的超集。”

本附录中似乎没有定义这些语法。

问题

可以在这里解决

4 在 pp-import 的所有三种形式中,导入和导出(如果存在)预处理标记分​​别替换为 import-keyword 和 export-keyword 预处理标记。

但我真的不知道这在语法方面意味着什么......这是什么意思?

有关的

一些相关的语法在这里(希望我可以帮助某人获得必要的信息,而不必遍历标准)。

 preprocessing-token:
    header-name
    import-keyword
    module-keyword
    export-keyword
    identifier
    pp-number
    character-literal
    user-defined-character-literal
    string-literal
    user-defined-string-literal
    preprocessing-op-or-punc
    each non-whitespace character that cannot be one of the above 
Run Code Online (Sandbox Code Playgroud)
 keyword:
    any identifier listed in Table 5
    import-keyword
    module-keyword
    export-keyword 
Run Code Online (Sandbox Code Playgroud)
module-import-declaration:
    import-keyword module-name attribute-specifier-seqopt ;
    import-keyword module-partition …
Run Code Online (Sandbox Code Playgroud)

c++ language-lawyer c++20

2
推荐指数
1
解决办法
994
查看次数