我在 Windows 10 和 Linux 中使用 Qt 5.7 执行相同的代码,但它只适用于 Linux。
我正在尝试确定我刚刚创建的 Ostream IOstream 的大小,因此它应该是空的。在 Linux 中 Size() 返回 0,但在 Windows 中它返回 -1,因为 tellp() 失败。
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <memory>
#include <sstream>
class Foo {
private:
std::shared_ptr<std::ostream> myOstream;
std::shared_ptr<std::istream> myIstream;
public:
Foo::Foo(std::shared_ptr<std::iostream> myIostream)
: myIstream(std::static_pointer_cast<std::istream>(myIostream))
, myOstream(std::static_pointer_cast<std::ostream>(myIostream))
{}
uint64_t Foo::Size() {
int ret = 0;
std::cout << "Before – Fail Flag: " << myOstream->fail() << ", Bad Bit: " << myOstream->bad() << std::endl;
if (myIstream.get() != nullptr) {
myIstream->clear();
auto oldPos = myIstream->tellg(); //returns 0
myIstream->seekg(0, std::ios_base::end);
ret = static_cast<int>(myIstream->tellg()); //returns 0
myIstream->seekg(oldPos);
}
if (myOstream.get() != nullptr) {
auto oldPos = myOstream->tellp(); //returns -1
myOstream->seekp(0, std::ios_base::end);
ret = static_cast<int>(myOstream->tellp()); //returns -1
myOstream->seekp(oldPos);
}
//Fail Flag returns -1, Bad Bit Flag returns 0
std::cout << "After – Fail Flag: " << myOstream->fail() << ", Bad Bit: " << myOstream->bad() << std::endl;
return static_cast<uint64_t>(ret);
}
};
int main()
{
auto myStringStream = std::make_shared<std::stringstream>(
std::ios::in | std::ios::out | std::ios::binary);
Foo foo(std::static_pointer_cast<std::iostream>(myStringStream));
std::cout << "Size: " << foo.Size() << std::endl;
system("pause");
return 0;
}
我得到 18446744073709551615
作为大小,因为它返回 -1,我将它转换为 uint64
。 Before Fail
和 Bad flag
都返回 0。After Fail
标志返回 1,Bad flag
返回 0 .
我读到这是因为哨兵的构建失败,但我不知道该怎么做才能修复它。
编辑:
在进一步研究代码之后,我意识到我遗漏了部分代码。我的理解是,为了获得大小,代码会计算出已经读取了多少,将指针调整到该位置,然后计算还剩多少并返回该值。但是由于 iostream 是新的并且它被转换为 .get() 返回内存位置并传递了 if 语句。然后 istream 部分将指针更改为最后,这就是 ostream 部分失败的原因。这是正确的吗?
编辑 2: 找到了解决方案。问题出在 myIstream->seekg(oldPos) 中,但是因为状态在 myIstream 和 myOstream 之间共享,所以直到调用 ostream 时才会捕获错误。字符串缓冲区是延迟分配的,但 seekp() 不适应这一点。解决此问题的方法是用垃圾数据填充字符串流,或者更好的方法是在使用之前检查它是否为空。
最佳答案
找到解决方案。问题出在 myIstream->seekg(oldPos) 中,但是因为状态在 myIstream 和 myOstream 之间共享,所以直到调用 ostream 时才会捕获错误。字符串缓冲区是延迟分配的,但 seekp() 不适应这一点。解决此问题的方法是用垃圾数据填充字符串流,或者更好的是在使用之前检查它是否为空。 – Namox9001
关于c++ - Ostream tellp 在 Windows 上失败但在 Linux 上没有,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40986375/