c++ - Simulink“访问冲突”写入 C++ lambda 函数捕获列表中的 PWork 变量
问题描述
我有一个 C++ S-Function,它通过 std::thread、std::async 和回调处理一组线程操作。问题是其中一个回调是一个 S-Function,它在捕获列表中有一个缓冲区。此缓冲区位于 Simulink 模型的 PWork 中。但是,似乎一旦我尝试写入 Matlab,它就会崩溃。
下面是我的 S-Function(仅 mdlStart 函数)的一个最小崩溃示例,其中包含相关代码:
static void mdlStart(SimStruct *S)
{
ssGetPWork(S)[0] = (void *) new ThreadedDataServer();
ssGetPWork(S)[1] = (void *) new DatagramAssembler();
ssGetPWork(S)[2] = (void *) new MyBufferType(); // actually an std::array<char, LARGENUMBER>
auto server = (ThreadedDataServer *) ssGetPWork(S)[0];
auto assembler = (DatagramAssembler*) ssGetPWork(S)[1];
auto copy_buffer_ptr = (MyBufferType *) ssGetPWork(S)[2];
server->attachDataHandler([©_buffer_ptr, &assembler](const ThreadedDataServer::buffer_t & buffer, size_t num_bytes)
{
/* Minimal crashing action */
copy_buffer_ptr->at(5) = 'b'; // Any index != 0
/* Original code */
//std::copy(buffer.begin(), buffer.begin() + num_bytes, copy_buffer_ptr->data());
//assembler->feedData(*copy_buffer_ptr, num_bytes);
});
}
从数据服务器工作线程(不同于 Simulink 主线程)调用处理程序。回调函数内的其他操作可以顺利进行(读取参数,执行其他操作......)。
任何提示为什么会发生这种情况?在将其集成到 Simulink 之前,相同的代码在一个独立的可执行文件中运行。
解决方案
您正在copy_buffer_ptr
通过引用捕获(堆栈局部变量)。该引用将在mdlStart
返回后立即悬空,之后调用 lambda 是未定义的行为。(这也适用于assembler
)。
解决方法是简单地捕获copy_buffer_ptr
并按assembler
值(它们是简单的指针,您可以毫无问题地复制它们):
server->attachDataHandler([copy_buffer_ptr, assembler](const ThreadedDataServer::buffer_t & buffer, size_t num_bytes)
{
/* etc. */
});
如果你有一个 lambda 会比当前范围更长寿,那么在通过引用捕获任何东西之前要仔细考虑——如果它是堆栈本地的,你可能会被烧毁。
推荐阅读
- python - 替换 2d numpy 数组中的一行
- python - 无法将令牌写入缓存:.cache
- python - 将 txt 文件从 Google Drive 导入到 Google Collab 时出错
- python - 从函数内部调用多个值
- c# - 如何将 Label.Text 转换为数字
- google-colaboratory - 在 colab 中从 Roboflow 加载数据集
- javascript - 是否可以旋转 iframe,然后分别旋转其中的内容,以实现底部滚动条的效果?
- azure - 是否可以创建具有特定 IP 地址的公共 ip?
- docker - 将 nginx 重定向到 ssl docker 服务
- android - 如何在活动中获取 navController?