boost,coroutine2(1.63.0):在32位窗口抛出异常崩溃visual studio
问题描述:
在我的应用程序中,我使用coroutine2来生成一些对象,我必须从流中解码。这些对象是使用协程生成的。我的问题是,只要我到达流的末尾,理论上会抛出std :: ios_base :: failure,在特定条件下我的应用程序崩溃。boost,coroutine2(1.63.0):在32位窗口抛出异常崩溃visual studio
提供此功能的函数在C++中实现,作为C函数导出并从C#调用。这一切都发生在Windows 10 x64的32位进程上。不幸的是,它只能在调试模式下从C#开始我的测试而没有附加本地调试器时可靠地崩溃。只要我连接本地调试器,一切都按预期工作。
这里是一个小的测试应用程序重现此问题:
Api.h
#pragma once
extern "C" __declspec(dllexport) int __cdecl test();
Api.cpp
#include <iostream>
#include <vector>
#include <sstream>
#include "Api.h"
#define BOOST_COROUTINES2_SOURCE
#include <boost/coroutine2/coroutine.hpp>
int test()
{
using coro_t = boost::coroutines2::coroutine<bool>;
coro_t::pull_type source([](coro_t::push_type& yield) {
std::vector<char> buffer(200300, 0);
std::stringstream stream;
stream.write(buffer.data(), buffer.size());
stream.exceptions(std::ios_base::eofbit | std::ios_base::badbit | std::ios_base::failbit);
try {
std::vector<char> dest(100100, 0);
while (stream.good() && !stream.eof()) {
stream.read(&dest[0], dest.size());
std::cerr << "CORO: read: " << stream.gcount() << std::endl;
}
}
catch (const std::exception& ex) {
std::cerr << "CORO: caught ex: " << ex.what() << std::endl;
}
catch (...) {
std::cerr << "CORO: caught unknown exception." << std::endl;
}
});
std::cout << "SUCCESS" << std::endl;
return 0;
}
C#:
using System;
using System.Runtime.InteropServices;
namespace CoroutinesTest
{
class Program
{
[DllImport("Api.dll", EntryPoint = "test", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
internal static extern Int32 test();
static void Main(string[] args)
{
test();
Console.WriteLine("SUCCESS");
}
}
}
一些细节:
- 我们使用Visual Studio 2015 14并动态链接C++运行库。
- 测试库静态链接Boost 1.63.0。
- 我们还尝试通过直接从C++和python调用functionallity来重现此行为。到目前为止,这两项测试都没有成功。
- 如果你用CTRL F5(意思是没有.net调试器)启动c#代码,一切都会好起来的。只有当你用F5启动它(意味着附加的.NET调试器)时,Visual Studio实例才会崩溃。另外请确保不要启用本地调试器!
- 注意:如果我们不使用流中的例外,那么所有接缝也都可以。不幸的是,解码我的对象的代码使用它们,因此我无法避免这种情况。
如果您对这里可能出现的问题或解决方案有一些额外的提示,那将是惊人的。我不完全确定这是否是一个提升错误,也可能是c#调试器干扰boost-context。
在此先感谢!最好的问候,迈克尔
答
这只是一个猜测,但在你的协同程序中,我认为你应该将一个布尔值推送到你的接收器(在代码中命名为yield)并且代码没有这样做。
这只是为了简化重现问题的示例。 这个问题发生之前,我们甚至得到这么多。协程创建后,尝试执行一些流操作,并在它甚至到达那个之前抛出异常。 – MichaelE1000