Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/138.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ Boost asio无故退出,代码为0。在有问题的语句后设置断点可以解决问题_C++_Boost_Boost Asio - Fatal编程技术网

C++ Boost asio无故退出,代码为0。在有问题的语句后设置断点可以解决问题

C++ Boost asio无故退出,代码为0。在有问题的语句后设置断点可以解决问题,c++,boost,boost-asio,C++,Boost,Boost Asio,我正在用boost asio编写一个TCP服务器客户端对。它非常简单和同步 服务器应该通过对通过TCP传输数据包的函数的多次递归调用来传输大量二进制数据。客户端通过从套接字读取传入数据包的递归函数进行模拟、读取和追加数据 然而,在接收此数据的中间,大多数时间(大约80%)客户端突然停止递归,总是在一个读调用之前(如下所示)。它不应该能够做到这一点,因为递归之后还有其他几个语句和函数调用 size_t bytes_transferred = m_socket.read_some(boost::as

我正在用boost asio编写一个TCP服务器客户端对。它非常简单和同步

服务器应该通过对通过TCP传输数据包的函数的多次递归调用来传输大量二进制数据。客户端通过从套接字读取传入数据包的递归函数进行模拟、读取和追加数据

然而,在接收此数据的中间,大多数时间(大约80%)客户端突然停止递归,总是在一个读调用之前(如下所示)。它不应该能够做到这一点,因为递归之后还有其他几个语句和函数调用

size_t bytes_transferred = m_socket.read_some(boost::asio::buffer(m_fileReadBuffer, m_fileReadBuffer.size()));
m_fileReadBuffer是一个大小为4096的boost::字符数组(尽管我也尝试过其他缓冲区格式,但没有成功)

我绝对无法想象推断出为什么会发生这种情况

  • 程序立即退出,因此我无法传递错误代码来读取某些和任何错误消息,因为这需要在read_some语句之后发生
  • 没有抛出异常
  • 编译/运行时没有错误或警告
  • 如果我在递归函数中设置断点,则问题永远不会发生(传输成功完成)
  • 如果我在传输后放置断点,或者在传输后将执行陷于while循环中,那么问题永远不会发生,也没有任何错误的迹象
另外,需要注意的是,服务器总是成功地发送所有数据。最重要的是,问题总是发生在传输的最后:我可以发送8000字节,当传输了大约6000或7000字节时,它将退出;我可以发送8000000字节,当传输了大约7996000字节时,它将退出

我可以提供任何必要的代码,只是不知道问题出在哪里。以下是客户端上的递归读取函数:

void TCP_Client::receive_volScan_message()
{
    try
    {
        //If the transfer is complete, exit this loop
        if(m_rollingSum >= (std::streamsize)m_fileSize)
        {
            std::cout << "File transfer complete!\n";
            std::cout << m_fileSize << " "<< m_fileData.size() << "\n\n";               

            return;
        }

        boost::system::error_code error;        

        //Transfer isn't complete, so we read some more        
        size_t bytes_transferred = m_socket.read_some(boost::asio::buffer(m_fileReadBuffer, m_fileReadBuffer.size()));

        std::cout << "Received " << (std::streamsize)bytes_transferred << " bytes\n"; 

        //Copy the bytes_transferred to m_fileData vector. Only copies up to m_fileSize bytes into m_fileData
        if(bytes_transferred+m_rollingSum > m_fileSize) 
        {
            //memcpy(&m_fileData[m_rollingSum], &m_fileReadBuffer, m_fileSize-m_rollingSum);
            m_rollingSum += m_fileSize-m_rollingSum;
        }
        else
        {
           // memcpy(&m_fileData[m_rollingSum], &m_fileReadBuffer, bytes_transferred);
            m_rollingSum += (std::streamsize)bytes_transferred;  
        }                     

        std::cout << "rolling sum: " << m_rollingSum << std::endl;

        this->receive_volScan_message();
    }
    catch(...)
    {
        std::cout << "whoops";
    }                
}
void TCP\u客户端::接收\u volScan\u消息()
{
尝试
{
//如果传输完成,则退出此循环
if(m_rollingSum>=(std::streamsize)m_fileSize)
{

我还没有完全理解这个问题,但是我已经设法完全解决了

问题的根源在于,在客户端上,如果服务器消息尚未到达,则
boost::asio::read
调用会以代码0退出

while(m_socket.available() == 0)
{
    ;
}  
在所有读取调用完全阻止问题之前。在调试和发布模式下

这是非常奇怪的,因为据我所知,这些函数应该一直阻塞,直到有东西要读,即使遇到错误,它们也应该返回零

我认为出现调试/发布差异是因为每当发生读取调用时,
m_readBuffer
没有初始化为任何内容。这使得
read
调用返回某种形式的静默错误。在调试时,未初始化的变量会自动设置为
NULL
,悄悄地解决了我的问题

不过,我不知道为什么在传输后添加while循环可以防止问题的发生,也不知道为什么它通常发生在传输结束时,在设置了m_readBuffer并成功使用了多次之后


除此之外,我从未见过这种“撞车”以前,程序只是在一个随机位置退出,代码为0,没有抛出错误或异常。

“通过多次递归调用”这听起来不太正确。为什么它必须是递归的?可能是一些时间问题,也可能是某个地方的问题?或者可能是因为递归太多,以致于你填满了堆栈,而调用无法完成使用导致程序崩溃的堆栈溢出?@πάνταῥεῖ 这是一种简单的方法。函数检查是否所有数据都已传输,如果未传输,则发送一些数据并调用自身。@Daniel一个简单的循环就足够了。我仍然不认为使用递归有任何意义。@JoachimPileborg我测试了发送和接收消息之间存在较大延迟的时间问题,但仍然发生了这种情况。此外,我正在测试小文件,因此通常会有3或4个递归调用,这样的溢出肯定不会不被注意地通过。这似乎不是正确的解决方案。您的客户端如何知道希望从服务器获得多少数据?@SamMiller该文件始终有一个固定大小的头,其中包含文件大小等信息。while(m_socket.available()==0)调用在客户端等待读取此头时发生,在客户端等待读取文件内容(紧跟其后)时再次发生。我仍然不明白为什么读取函数在有数据读取之前不会自然阻塞,就像它们应该执行的那样。读取函数确实会按照请求执行阻塞操作,我怀疑您的问题出在其他地方,因为您没有发布消息。