【问题标题】:Calling serial_port::cancel causes Run-Time Check Failure #0 on Visual Studio 2010 SP1在 Visual Studio 2010 SP1 上调用 serial_port::cancel 会导致运行时检查失败 #0
【发布时间】:2012-03-15 12:47:04
【问题描述】:

这是一个致命错误,无法从中恢复,并且在发布版本中,会出现一个令人讨厌的消息框。当我调用 serial_port::cancel 并且 Boost 尝试抛出一些异常时会发生这种情况。确切的错误是:

运行时检查失败 #0 - ESP 的值未正确保存 通过函数调用。这通常是调用 用一个调用约定和一个函数指针声明的函数 使用不同的调用约定声明。

而且它似乎发生在 throw_error.ipp 中的 do_throw_error 方法中。 这是一个重现此内容的小示例程序:

#include <boost/asio/serial_port.hpp>
#include <boost/asio/read.hpp>
#include <boost/thread.hpp>
#include <iostream>

using namespace std;

BYTE g_pBuffer[128];

void ReadCompletionHandler( boost::system::error_code ec, std::size_t bytesTransferred ){
    if( !ec ){
        cout << "Read " << bytesTransferred << " bytes successfully" << endl;
    }else if( ec == boost::asio::error::operation_aborted ){
        cout << "Aborted async_read_some, " << bytesTransferred << " bytes transferred" << endl;
    }else{
        cout << "Read finished with errors: " << ec.message() << endl;
    }
}

void ReaderThread( boost::asio::serial_port* pSerialPort ){
    cout << "[ReaderThread] Started reading" << endl;
    boost::asio::async_read( *pSerialPort, boost::asio::buffer( g_pBuffer, 5 ), ReadCompletionHandler );
    cout << "[ReaderThread] Done!" << endl;
}

void main(){
    //Tell cout not to buffer its output so output better reflects multithreaded execution
    std::cout.setf(std::ios::unitbuf);
    boost::asio::io_service ioService;
    boost::asio::serial_port serialPort( ioService );
    string portName = "COM1";
    serialPort.open( portName );
    if( !serialPort.is_open() ){
        cout << "Failed to open " << portName << endl;
        return;
    }
    cout << "Launching reader thread and io_service" << endl;
    boost::thread readerThread( boost::bind( ReaderThread, &serialPort ) );
    ioService.run();
    cout << "Sleeping..." << endl;
    ::Sleep( 5000 );
    cout << "Woke up, cancelling pending reads" << endl;
    serialPort.cancel();
    cout << "Waiting for reader thread to finish..." << endl;
    readerThread.join();
    cout << "Done!" << endl;
    cin.get();
}

也许我在做一些愚蠢的事情。你怎么看?

【问题讨论】:

  • AFAIK,完成处理程序需要 _stdcall 调用约定。
  • 将 __stdcall 添加到 ReadCompletionHandler 的定义并没有解决它。如果我将项目的调用约定更改为 __stdcall,它将停止构建。因此,Boost 似乎是使用 __cdecl 约定构建的。我应该重建 Boost 以便它使用 __stdcall 吗?

标签: c++ visual-studio-2010 serial-port boost-asio


【解决方案1】:

在 Windows XP 中,serial_port::cancel 调用 CancelIo,这会取消 调用 线程的待处理 I/O。所以解决方案是将调用调度到io_service::run 正在运行的线程:

ioService.post( [&]{serialPort.cancel();} );

非常感谢 boost-users 列表中的人(Igor R 和 Richard Rowlands)。 无论如何,我认为 Boost 应该检查调用线程是否是串口的所有者,我的意思是,取消不是你会密集调用的操作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多