Search code examples
c++visual-studioboostboost-coroutine2

boost, coroutine2 (1.63.0): throwing exception crashes visual studio on 32bit windows


In my application I'm using coroutine2 to generate some objects which I have to decode from a stream. These objects are generated using coroutines. My problem is that as soon as I reach the end of the stream and would theoretically throw std::ios_base::failure my application crashes under certain conditions.

The function providing this feature is implemented in C++, exported as a C function and called from C#. This all happens on a 32bit process on Windows 10 x64. Unfortunately it only reliably crashes when I start my test from C# in debugging mode WITHOUT the native debugger attached. As soon as I attach the native debugger everything works like expected.

Here is a small test application to reproduce this issue:

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");
        }
    }
}

Some details:

  • We are using Visual Studio 2015 14 and dynamically link the c++ runtime.
  • The test library statically links Boost 1.63.0.
  • We also tried to reproduce this behaviour with calling the functionallity directly from c++ and from python. Both tests have not been successful so far.
  • If you start the c# code with CTRL F5 (meaning without the .net debugger) everything will also be fine. Only if you start it with F5 (meaning the .NET Debugger attached) the visual studio instance will crash. Also be sure not to enable the native debugger!
  • Note: If we don't use the exceptions in the stream, everything seams to be fine as well. Unfortunately the code decoding my objects makes use of them and therefore I cannot avoid this.

It would be amazing if you had some additional hints on what might go wrong here or a solution. I'm not entirely sure if this is a boost bug, could also be the c# debugger interfering with boost-context.

Thanks in advance! Best Regards, Michael


Solution

  • I realize this question is old but I just finished reading a line in the docs that seemed pertinent:

    Windows using fcontext_t: turn off global program optimization (/GL) and change /EHsc (compiler assumes that functions declared as extern "C" never throw a C++ exception) to /EHs (tells compiler assumes that functions declared as extern "C" may throw an exception).