C++ 为什么这个没有设置错误标志的文件流无法读取,除非我执行tellg()?
我有一个fstream,它似乎进入了幻象故障状态,即使检查它(通过转换为C++ 为什么这个没有设置错误标志的文件流无法读取,除非我执行tellg()?,c++,c++11,fstream,c++03,libstdc++,C++,C++11,Fstream,C++03,Libstdc++,我有一个fstream,它似乎进入了幻象故障状态,即使检查它(通过转换为bool)没有显示任何错误标志。后续读取失败,这是意外的 #include <fstream> #include <iostream> #include <cassert> int main() { const unsigned int SAMPLE_COUNT = 2; // Setup - create file with two "samples"; each s
bool
)没有显示任何错误标志。后续读取失败,这是意外的
#include <fstream>
#include <iostream>
#include <cassert>
int main()
{
const unsigned int SAMPLE_COUNT = 2;
// Setup - create file with two "samples"; each sample has a double and a float
{
std::ofstream ofs("/tmp/ffs", std::ios::binary);
const double colA[SAMPLE_COUNT] = { 1.0, 2.0 };
const float colB[SAMPLE_COUNT] = { 42.0, 100.0 };
for (size_t i = 0; i < SAMPLE_COUNT; i++) {
ofs.write((char*)&colA[i], sizeof(colA[i]));
ofs.write((char*)&colB[i], sizeof(colB[i]));
}
}
// Actual testcase
{
std::fstream fs("/tmp/ffs", std::ios::binary | std::ios::out | std::ios::in);
assert(fs);
unsigned int sample_n = 0;
while (true) {
double a;
fs.read((char*)&a, sizeof(a));
if (!fs) {
std::cerr << "No more samples\n";
break;
}
std::cerr << "Sample " << (++sample_n) << " first column = " << a << '\n';
// Read column B
float b;
fs.read((char*)&b, sizeof(b));
assert(fs);
std::cerr << "Current value second column = " << b << '\n';
// Multiply it by two and write back
b *= 2;
fs.seekp(-sizeof(b), std::ios::cur);
fs.write((char*)&b, sizeof(b));
assert(fs);
#ifdef DO_THE_TELLG
// Unless I do this, the `fs.read` on the next iteration fails!
// So the loop ends, and I get only the first sample transformed in my file.
fs.tellg();
#endif
}
}
// Inspection - should see values 84 and 200, but see 84 and 100 instead.
{
std::ifstream ifs("/tmp/ffs", std::ios::binary);
std::cerr << "All values at end:\n";
for (size_t i = 0; i < SAMPLE_COUNT; i++) {
double a;
float b;
ifs.read((char*)&a, sizeof(a));
ifs.read((char*)&b, sizeof(b));
std::cerr << a << '\t' << b << '\n';
}
assert(ifs);
}
}
如果对其执行tellg()
或tellp()
操作,则后续读取成功,因此循环不会过早结束,第二个样本也会乘以2,以生成200
:
这仅在以下环境中发生:
- CentOS 6 x86_64,通用条款4.4.7
- CentOS 6 x86_64,GCC 4.8.2(通过devtoolset-2)
tellg()
/tellp()
:
- CentOS 7
更新:好的,那么。但是Dietmar没有说明这是标准强制的还是libstdc++错误。对我来说,这看起来像是,但这是
解决的
/WONTFIX
,那么为什么我的程序在Coliru和CentOS 7下会像预期的那样工作呢?理想情况下,在实施此解决方案之前,我希望能够更准确地掌握正在发生的事情。这是标准要求。请参阅@n.m.:“因此,您的stream.seekp(1)解决方案(该解决方案已移交给C fseek)是正确的。”seekp的工作方式是否强制要求如此?那么,它是如何在CentOS 7上工作的呢?公认的答案是GNUC库没有这个限制,但这不是我在CentOS 6上的经验。所以现在我更糊涂了!关于glibc的说法可能是正确的,也可能是错误的,也可能只是指一些glibc版本。我从未在文档中看到过它的确认。这个解决方案已经实施了几个月,显然效果很好。但我还是想知道“心安”的官方说法。
[root@localhost ~]# ./test
Sample 1 first column = 1
Current value second column = 42
No more samples
All values at end:
1 84
2 100
[root@localhost ~]# ./test
Sample 1 first column = 1
Current value second column = 42
Sample 2 first column = 2
Current value second column = 100
No more samples
All values at end:
1 84
2 200