【发布时间】:2016-08-08 16:01:14
【问题描述】:
我无法从使用 boost::asio::windows::stream_handle 的文件异步读取超过 65536 字节到缓冲区。
从65537th 字节开始,缓冲区包含文件开头的数据,而不是预期的数据。
这是一个重现问题的代码示例:
auto handle = ::CreateFile(L"BigFile.xml", GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, nullptr);
boost::asio::io_service ios;
boost::asio::windows::stream_handle streamHandle(ios, handle);
const auto to_read_bytes = 100000;
char buffer[to_read_bytes];
boost::asio::async_read(streamHandle, boost::asio::buffer(buffer, to_read_bytes), [](auto &ec, auto read) {
std::cout << "Bytes read: " << read << std::endl;
});
ios.run();
auto bufferBegin = std::string(buffer, 38);
auto bufferCorrupted = std::string(buffer + 65536, 38); // <- it contains bytes from the beginning of the file
std::cout << "offset 0: " << bufferBegin << std::endl;
std::cout << "offset 65536: " << bufferCorrupted << std::endl;
::CloseHandle(handle);
该代码产生一个输出:
> Bytes read: 100000
> offset 0: <?xml version="1.0" encoding="UTF-8"?>
> offset 65536: <?xml version="1.0" encoding="UTF-8"?>
源文件大于 65536。
这可以通过 boost 1.61 + VS2015 重现。这个问题也出现在 boost 1.55 + VS2010 中。
操作系统有:Windows 7 和 Windows Server 2008R2。
我的问题是:
1.这是boost::asio或WinAPI的已知限制吗?
2. 如果是已知限制,读取数据的缓冲区的安全大小是多少?缓冲区大小为 65536 是否安全,或者应该更小?
【问题讨论】:
-
这不是 Windows API 中的限制——那里存在的限制(在旧 API 方法中)是 2^32 而不是 2^16。
-
您可能需要指定您正在使用的软件版本(boost、windows 和 Visual C++)
-
@nate 是的,我肯定需要指定版本。谢谢提醒。我相应地更新了问题。
-
问题可能出在堆栈限制上,通常为 100,000。使用在堆上分配内存的
std::string,而不是在堆栈上分配的char buffer[100000];。或者只是使用to_read_bytes = 4096,如果增加缓冲区大小,它不会变得更快。 -
@BarmakShemirani 不,这不是堆栈限制。同样的行为是在堆中分配缓冲区时。
标签: c++ winapi boost boost-asio