【发布时间】:2015-09-16 04:59:35
【问题描述】:
以下代码读取一个文件,其中包含一些值,该值表示更多后续数据的长度。
auto file = std::ifstream(filename, std::ios::in | std::ios::binary);
// dataLen = Read some header field containing a length of following data.
std::vector<unsigned char> data;
data.resize(dataLen);
file.read((char*)data.data(), dataLen);
如果 dataLen = 0,MSVC 2013 编译器会失败。它会通过消息Expression: invalid null pointer 导致中止,因为data.data() 返回一个空指针。
This question 表明 count 为 0 对 std::basic_istream::read 有效,但关于该问题的第三条评论似乎指出了我的问题。
将无效指针传递给大小为 0 的 std::basic_istream::read(或 std::basic_ostream::write)是否有效?这对我来说似乎是合乎逻辑的,因为无论如何调用都不应该触及缓冲区。
显而易见的解决方案是使用 if 子句处理这种特殊情况,但我想知道 MSVC 是否又错了。
这是一个编译好的clang运行程序示例:http://coliru.stacked-crooked.com/a/c036ec31abd80f22
【问题讨论】:
-
为了澄清,“它会导致消息中止......” - 这是由未捕获的异常触发的吗?或者它是 VS 标准 C++ 库的调试二进制文件中的运行时 assertion。可能看起来差别不大,但它是相关的。在 release 构建中是否有相同的行为?
-
@WhozCraig 它说
Debug Assertion Failed!,并且不会在发布版本中发生。 -
@typ1232 那么为什么不在调试模式下只做
data.resize(dataLen + 1)? -
@Barry 因为以后使用
data.size()不再精确到实际读取数据的大小。虽然后续数据.resize(dataLen);会解决这个问题,但以上所有内容都是 OP 问题的重点:首先是否需要这样的箍。 -
@typ1232 我也很怀疑。 MS 试图通过告诉您传入的指针无效来“提供帮助”。该断言应该包括对声称的缓冲区大小也非零的验证。在审查标准时,即使没有提取数据,也会对缓冲区进行单字符写入,但这取决于传递的非零长度。但是在您的情况下,所述长度为零,因此不适用。如果 MS 抛出运行时异常,我会觉得这很可悲(对 MS 来说不是不熟悉的领域),但我只能将其归类为普通的恼人。
标签: c++ c++11 iostream ostream istream