std::iostream读取或写入计数为零且缓冲区无效
std::iostream read or write with count zero and invalid buffer
下面的代码读取一个文件,该文件包含一些表示后面更多数据长度的值。
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编译器一起失败。由于data.data()
返回一个空指针,因此会导致消息Expression: invalid null pointer
中止。
这个问题表明0的count
对std::basic_istream::read
有效,但对这个问题的第三条评论似乎指出了我的问题。
将无效指针传递给大小为0的std::basic_istream::read
(或std::basic_ostream::write
)是否是有效的C++?对我来说,这似乎是合乎逻辑的,因为无论如何,调用都不应该触及缓冲区。
显而易见的解决方案是用if子句来处理这种特殊情况,但我想知道MSVC是否又错了。
以下是clang运行程序fine的编译示例:http://coliru.stacked-crooked.com/a/c036ec31abd80f22
以下是标准在27.7.2.3[isream.unformated]第30段和第31段中对std::basic_istream<...>::read()
的说明(重点是我的):
basic_istream<charT,traits>& read(char_type* s, streamsize n);
效果:表现为未格式化的输入函数(如27.7.2.3第1段所述)。在构造了一个
sentry
对象之后,如果!good()
调用setstate(failbit)
,可能会抛出异常,并返回。否则,提取字符并将其存储到数组的连续位置,该数组的第一个元素由s
指定。提取并存储字符,直到出现以下任一情况:
- 存储CCD_ 13个字符
- 文件结尾出现在输入序列上(在这种情况下,函数调用
setstate(failbit | eofbit)
,它可能抛出ios_base::failure
)返回:
*this
。
当一个函数被描述为以数组为自变量时,根据17.6.4.9[res.on.arguments]第1段(省略的文本适用于其他实体),对可以传递的内容有一些限制:
除非另有明确说明,否则以下各项均适用于C++标准库中定义的函数的所有参数。
- 如果函数的参数具有无效值(例如函数域外的值或对其预期用途无效的指针),则行为是未定义的
- 如果函数参数被描述为数组,则实际传递给该函数的指针应具有一个值,以便所有地址计算和对对象的访问(如果指针确实指向此类数组的第一个元素,则将有效)实际上都是有效的
根据8.3.4[dcl.array]第1段的规定,实际数组不能为空(注意,不存在常量表达式的情况下会产生一个未指定大小的数组,该数组最终仍为非零大小):
如果存在常量表达式,则它应为std::size_t类型的转换常量表达式,并且其值应更大大于零。。。
由于null指针不能指向非空数组,因此期望传递数组的函数应该是非null指针。换句话说,我认为您观察到的断言是完全有序的,将定义的行为赋予了根据标准具有未定义行为的使用:即使传递给read()
的大小为零,空指针也会根据标准产生未定义行为。
- C++字符*缓冲区的大小
- Openssl 1.1.1d无效使用不完整的类型"struct dsa_st"
- 无法访问嵌套类.类的使用无效
- 为什么msgrcv()将垃圾字符馈送到缓冲区
- 使用动态分配的数组会导致代码分析发出虚假的C6386缓冲区溢出警告
- ostream过载时的缓冲区冲洗
- C++中的高效循环缓冲区,它将被传递给C样式数组函数参数
- Xaudio2在更改缓冲区或循环时弹出声音
- 为什么我在leetcode上收到AddressSanitizer:地址0x602000000058上的堆缓冲区溢出错误
- 如果用户输入无效,如何使用字符串变量-C++重复输入命令
- 如何将图像传输到c++(dll)中的缓冲区,然后在c#的缓冲区中读/写
- 跨平台套接字发送,Linux 上的缓冲区常量无效* Windows上的常量字符*,最佳处理方式
- 读取文本文件会导致缓冲区末尾的字符无效
- 将缓冲区与字符进行比较是无效的
- MPI_scatter:缓冲区指针无效
- 检测环形缓冲区的无效迭代器
- 使用核心配置文件交换缓冲区使用了无效操作
- read() 缓冲区有无效数据(指针问题?
- MPI_Pack:无效缓冲区指针
- std::iostream读取或写入计数为零且缓冲区无效