Asio 协程在使用右值参数时表现不佳?

2024-04-01

我可能做了一些明显错误的事情,但为什么会在 MSVC 上打印垃圾?

#include <sdkddkver.h>

#include <boost/asio.hpp>
#include <iostream>

namespace asio = boost::asio;

template <typename Str>
asio::awaitable<void> coro_task(Str&& str) {
  std::cout << "coro_task: " << str << std::endl;
  co_await asio::this_coro::executor;
}

template <typename Str>
void sync_task(Str&& str) {
  std::cout << "sync_task: " << str << std::endl;
}

int main() {
  asio::io_context ioc;
  asio::co_spawn(ioc.get_executor(), coro_task("hello world"), asio::detached);
  asio::post(ioc.get_executor(), [] { sync_task("hello world"); });

  ioc.run();
}

例如:

coro_task: ╕÷ⁿäg
sync_task: hello world

我不明白为什么会这样。一定Str将是静态生命周期char[12] &,所以我不明白为什么它会得到垃圾数据。

如果我将任何具有暂时生命周期的东西传递给coro_task (e.g. coro_task(std::string{"hello world"}))我没有得到输出(str是空的)。我猜想它是从某个地方搬来的,但不知道在哪里。

尝试为阻塞函数创建通用异步任务/协程包装器时遇到此问题:https://stackoverflow.com/a/75228866/3554391 https://stackoverflow.com/a/75228866/3554391。这个问题代表了这个问题的一个最小例子。

该问题似乎没有发生与 godbolt 上的 gcc 一起使用 https://godbolt.org/#g:!((g:!((g:!((h:codeEditor,i:(filename:%271%27,fontScale:14,fontUsePx:%270%27,j:1,lang:c%2B%2B,selection:(endColumn:2,endLineNumber:23,positionColumn:2,positionLineNumber:23,selectionStartColumn:2,selectionStartLineNumber:23,startColumn:2,startLineNumber:23),source:%27%23include+%3Cboost/asio.hpp%3E%0A%23include+%3Ciostream%3E%0A%0Anamespace+asio+%3D+boost::asio%3B%0A%0Atemplate+%3Ctypename+Str%3E%0Aasio::awaitable%3Cvoid%3E+coro_task(Str%26%26+str)+%7B%0A++std::cout+%3C%3C+%22coro_task:+%22+%3C%3C+str+%3C%3C+std::endl%3B%0A++co_await+asio::this_coro::executor%3B%0A%7D%0A%0Atemplate+%3Ctypename+Str%3E%0Avoid+sync_task(Str%26%26+str)+%7B%0A++std::cout+%3C%3C+%22sync_task:+%22+%3C%3C+str+%3C%3C+std::endl%3B%0A%7D%0A%0Aint+main()+%7B%0A++asio::io_context+ioc%3B%0A++asio::co_spawn(ioc.get_executor(),+coro_task(%22hello+world%22),+asio::detached)%3B%0A++asio::post(ioc.get_executor(),+%5B%5D+%7B+sync_task(%22hello+world%22)%3B+%7D)%3B%0A%0A++ioc.run()%3B%0A%7D%27),l:%275%27,n:%270%27,o:%27C%2B%2B+source+%231%27,t:%270%27)),k:59.375,l:%274%27,n:%270%27,o:%27%27,s:0,t:%270%27),(g:!((g:!((h:compiler,i:(compiler:g131,deviceViewOpen:%271%27,filters:(b:%270%27,binary:%271%27,binaryObject:%271%27,commentOnly:%270%27,debugCalls:%271%27,demangle:%270%27,directives:%270%27,execute:%270%27,intel:%270%27,libraryCode:%270%27,trim:%271%27),flagsViewOpen:%271%27,fontScale:14,fontUsePx:%270%27,j:1,lang:c%2B%2B,libs:!((name:boost,ver:%27182%27)),options:%27-std%3Dc%2B%2B20+-Wall+-Wextra+-pedantic+-Werror+-lpthread%27,overrides:!(),selection:(endColumn:1,endLineNumber:1,positionColumn:1,positionLineNumber:1,selectionStartColumn:1,selectionStartLineNumber:1,startColumn:1,startLineNumber:1),source:1),l:%275%27,n:%270%27,o:%27+x86-64+gcc+13.1+(Editor+%231)%27,t:%270%27)),header:(),l:%274%27,m:70.82658022690438,n:%270%27,o:%27%27,s:0,t:%270%27),(g:!((h:output,i:(compilerName:%27x86-64+gcc+13.1%27,editorid:1,fontScale:14,fontUsePx:%270%27,j:1,wrap:%271%27),l:%275%27,n:%270%27,o:%27Output+of+x86-64+gcc+13.1+(Compiler+%231)%27,t:%270%27)),header:(),l:%274%27,m:29.17341977309562,n:%270%27,o:%27%27,s:0,t:%270%27)),k:40.625,l:%273%27,n:%270%27,o:%27%27,t:%270%27)),l:%272%27,n:%270%27,o:%27%27,t:%270%27)),version:4 or 伴随着铿锵声 https://godbolt.org/#g:!((g:!((g:!((h:codeEditor,i:(filename:%271%27,fontScale:14,fontUsePx:%270%27,j:1,lang:c%2B%2B,selection:(endColumn:2,endLineNumber:23,positionColumn:2,positionLineNumber:23,selectionStartColumn:2,selectionStartLineNumber:23,startColumn:2,startLineNumber:23),source:%27%23include+%3Cboost/asio.hpp%3E%0A%23include+%3Ciostream%3E%0A%0Anamespace+asio+%3D+boost::asio%3B%0A%0Atemplate+%3Ctypename+Str%3E%0Aasio::awaitable%3Cvoid%3E+coro_task(Str%26%26+str)+%7B%0A++std::cout+%3C%3C+%22coro_task:+%22+%3C%3C+str+%3C%3C+std::endl%3B%0A++co_await+asio::this_coro::executor%3B%0A%7D%0A%0Atemplate+%3Ctypename+Str%3E%0Avoid+sync_task(Str%26%26+str)+%7B%0A++std::cout+%3C%3C+%22sync_task:+%22+%3C%3C+str+%3C%3C+std::endl%3B%0A%7D%0A%0Aint+main()+%7B%0A++asio::io_context+ioc%3B%0A++asio::co_spawn(ioc.get_executor(),+coro_task(%22hello+world%22),+asio::detached)%3B%0A++asio::post(ioc.get_executor(),+%5B%5D+%7B+sync_task(%22hello+world%22)%3B+%7D)%3B%0A%0A++ioc.run()%3B%0A%7D%27),l:%275%27,n:%270%27,o:%27C%2B%2B+source+%231%27,t:%270%27)),k:59.375,l:%274%27,n:%270%27,o:%27%27,s:0,t:%270%27),(g:!((g:!((h:compiler,i:(compiler:clang1600,deviceViewOpen:%271%27,filters:(b:%270%27,binary:%271%27,binaryObject:%271%27,commentOnly:%270%27,debugCalls:%271%27,demangle:%270%27,directives:%270%27,execute:%270%27,intel:%270%27,libraryCode:%270%27,trim:%271%27),flagsViewOpen:%271%27,fontScale:14,fontUsePx:%270%27,j:1,lang:c%2B%2B,libs:!((name:boost,ver:%27182%27)),options:%27-std%3Dc%2B%2B20+-Wall+-Wextra+-pedantic+-Werror+-pthread%27,overrides:!(),selection:(endColumn:1,endLineNumber:1,positionColumn:1,positionLineNumber:1,selectionStartColumn:1,selectionStartLineNumber:1,startColumn:1,startLineNumber:1),source:1),l:%275%27,n:%270%27,o:%27+x86-64+clang+16.0.0+(Editor+%231)%27,t:%270%27)),header:(),l:%274%27,m:70.82658022690438,n:%270%27,o:%27%27,s:0,t:%270%27),(g:!((h:output,i:(compilerName:%27x86-64+gcc+13.1%27,editorid:1,fontScale:14,fontUsePx:%270%27,j:1,wrap:%271%27),l:%275%27,n:%270%27,o:%27Output+of+x86-64+clang+16.0.0+(Compiler+%231)%27,t:%270%27)),header:(),l:%274%27,m:29.17341977309562,n:%270%27,o:%27%27,s:0,t:%270%27)),k:40.625,l:%273%27,n:%270%27,o:%27%27,t:%270%27)),l:%272%27,n:%270%27,o:%27%27,t:%270%27)),version:4.

我正在使用 Visual Studio 17.5.5 和 asio 1.25.0。


从广义上讲,协程不应该通过引用获取参数。不同于,例如,std::async,C++ 的协程系统尝试将引用参数转换为本地副本的努力为零。

这解释了当你给它类似的对象时它的行为std::string。要理解它在直接处理字符串文字时的行为......事情变得复杂。

在普通函数中,参数是由调用函数有效创建的。由于协程must它比其函数调用引用的上下文更长寿,它有一种机制可以将参数“复制”到与协程状态关联的存储中。如果参数是值参数,则它将由原始参数的 xvalue 表达式初始化(​​因此可以从中移动)。但是,如果这些参数是参考参数,则“复制”将also可以作为同类型的参考。

这就是我们遇到一些问题的地方。用于转发字符串文字引用的模板参数推导会生成对字符串数组的引用。但这是对暂时的数组,通过使用字符串文字作为模板函数的参数来体现。如果该函数采取了char const*,那么所讨论的数组将是指向静态内存的指针。但相反,您拥有的是对临时对象的引用,该引用由函数的调用者拥有。

因此将在协程暂停的那一刻到期。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Asio 协程在使用右值参数时表现不佳? 的相关文章

随机推荐

  • Tkinter Windows 按键事件

    Tkinter 中 Windows 键的事件是什么 我使用的是 Linux 但我想要 Linux 和 Windows 的答案 如果 Mac 有类似的密钥 请随时告诉我它的绑定 我想左右 windows 键有不同的事件 Windows 键似乎
  • 将用户的时区与网站办公地点的时区进行比较

    我正在开发一个项目 我需要在联系人区域向网站访问者显示一条消息 例如 联系电话 91 99 3241 5285 You can call us now 该消息在上面一行中突出显示 现在我的问题是 如何将用户的时区与公司办公室的工作时间进行比
  • 从 Fluent Nhibernate 获取表名

    在流畅的 nhibernate 中设置映射后 有没有办法从类类型中获取实体的表名 我读过常规的 nhiberante 你可以做类似的事情cfg GetClassMapping typeof Employee 我想做这样的事情来检索数据库表名
  • 有没有办法在我的代码中使用 Typescript.Collections.HashTable ?

    我在 Typescript 编译器的代码中看到了 HashTable 的实现 在文件 src compiler core hashTable ts 中 你知道有没有办法可以直接在我的 Typescript 项目中使用它 您可以通过定义接口来
  • 将向量数组作为函数参数传递(值不会改变)

    我在一类中有一组向量 class MeasurementData private std vector
  • laravel 5 根据路由返回 HTML 或 JSON

    我想显示不同的输出 JSON 或 HTML 我无法使用 Request ajax 功能 因为我只是收到正常请求 JSON 响应不是基于 XHR 请求 是否有可能区分不同路线的输出 例如 检查控制器是否由前缀为 mob 的路由调用 然后根据该
  • 检测从 C# 应用程序最小化的所有窗口

    如何检测从 C 应用程序最小化的所有窗口 其他应用程序 使用这里的示例http pinvoke net default aspx user32 EnumDesktopWindows http pinvoke net default aspx
  • 单独运行时单个规范通过,但运行所有规范时失败

    我的 foo controller spec rb 中有 30 个规范 当我使用规范运行整个文件时 我得到 4 个失败和 2 个待处理 当我单独运行 4 个失败的规范时 其中 3 个仍然失败 但其中一个通过了 起初我认为这是一个数据库问题
  • C++ New 与 Malloc 用于对象的动态内存数组

    我有一个 Bullet 类 它的构造需要几个参数 但是 我使用动态内存阵列来存储它们 我正在使用 C 所以我想通过使用 new 运算符来分配内存来符合它的标准 问题是当我分配数组时 new 运算符要求构造函数参数 而当时我没有 我可以使用
  • 从表中删除*不起作用[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我正在尝试删除all rows从表中但它不起作用 当我做echo mydb gt error 它给了我以下内容 You have an e
  • Node-PerfectAPI vs Restify.js vs ExpressJS vs Node-APIServer [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 我是 ExpressJS 的新手 我想为我的服务创建 API 该服务将直接由其他服务器使用 并且一部分也由移动应用程序 浏览器使用 我刚刚发现了
  • Dagger 和 mvp - 演示者是否应该使用 dagger 进行注入

    我开始认为在mvp中 匕首不应该在presenter中使用 构造 dagger 的常用方法是使用全局组件并具有用于确定图形范围的子组件 该全局组件通常在创建 appmodule java 类时将 applicationContext 作为参
  • 如何在 Scala 中模拟“一次分配”变量?

    这是一个后续问题我之前的初始化变量问题 https stackoverflow com questions 4400926 can i define method private fields in scala 假设我们正在处理这样的上下文
  • Android Profiler 未出现在 Android Studio 中

    我想分析我的设备中的内存消耗 但我没有找到Android 分析器Android Studio 中的选项卡如下所示 请问谁能帮我显示这个选项卡 如果你看一下顶部菜单 你会看到个人资料图标单击它 它将启动您的应用程序并附加配置文件 请参阅下面的
  • Spark - Scala - saveAsHadoopFile 抛出错误

    我想解决该问题 但无法进一步进行 有人可以帮忙吗 import org apache hadoop mapred lib MultipleTextOutputFormat class KeyBasedOutput T gt Null V l
  • iOS 8 SpriteKit 在从块/操作中添加或删除子项时崩溃

    从 iOS8 开始 我的游戏突然开始崩溃 经过一番调试 我发现游戏在以下两个地方崩溃 sparkNode runAction SKAction sequence Some actions and finally SKAction remov
  • 在 Ruby 中读取文件的第一行

    我想读书only以最快 最简单 最惯用的方式使用 Ruby 来编写文件的第一行 最好的方法是什么 具体来说 我想从我最新的 Capistrano 部署的 Rails 目录中的 REVISION 文件中读取 git commit UUID 然
  • C# 字符串到长指针

    我正在使用 C 中的应用程序 需要向 C 应用程序发送消息 我导入了 DllImport user32 dll public static extern IntPtr SendMessage int hWnd handle to desti
  • jar 文件损坏

    我使用 eclipse 在 Windows 7 中创建了一个 jar 文件 当我尝试打开 jar 文件时 它显示 jar 文件无效或损坏 谁能告诉我为什么 jar 文件无效 当您在 Windows 资源管理器中双击 JAR 文件时会发生这种
  • Asio 协程在使用右值参数时表现不佳?

    我可能做了一些明显错误的事情 但为什么会在 MSVC 上打印垃圾 include