- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我公司的产品运行在许多合格的 Linux 硬件/软件配置上。从历史上看,使用的编译器是 GNU C++。出于本文的目的,让我们将版本 3.2.3 视为基线,因为我们的软件在该版本中“按预期工作”。
随着更新的合格平台的引入,使用 GNU C++ 版本 3.4.4,我们开始观察到一些以前从未见过的性能问题。经过一番挖掘,我们的一位工程师想出了这个测试程序:
#include <fstream>
#include <iostream>
using namespace std;
class my_filebuf : public filebuf
{
public:
my_filebuf() : filebuf(), d_underflows(0) {};
virtual ~my_filebuf() {};
virtual pos_type seekoff(off_type, ios_base::seekdir,
ios_base::openmode mode = ios_base::in | ios_base::out);
virtual int_type underflow();
public:
unsigned int d_underflows;
};
filebuf::pos_type my_filebuf::seekoff(
off_type off,
ios_base::seekdir way,
ios_base::openmode mode
)
{
return filebuf::seekoff(off, way, mode);
}
filebuf::int_type my_filebuf::underflow()
{
d_underflows++;
return filebuf::underflow();
}
int main()
{
my_filebuf fb;
fb.open("log", ios_base::in);
if (!fb.is_open())
{
cerr << "need log file" << endl;
return 1;
}
int count = 0;
streampos pos = EOF;
while (fb.sbumpc() != EOF)
{
count++;
// calling pubseekoff(0, ios::cur) *forces* underflow
pos = fb.pubseekoff(0, ios::cur);
}
cerr << "pos=" << pos << endl;
cerr << "read chars=" << count << endl;
cerr << "underflows=" << fb.d_underflows << endl;
return 0;
}
我们针对大约 751KB 字符的日志文件运行它。在前面的配置中,我们得到了结果:
$ buftest
pos=768058
read chars=768058
underflows=0
在较新的版本中,结果是:
$ buftest
pos=768058
read chars=768058
underflows=768059
注释掉 pubseekoff(0, ios::cur) 调用,过多的 underflow() 调用就会消失。很明显,在较新版本的 g++ 中,调用 pubseekoff() 会使缓冲区“无效”,从而强制调用 underflow()。
我已经阅读了标准文档,pubseekoff() 上的措辞肯定是模棱两可的。例如,底层文件指针位置与 gptr() 的位置有什么关系?在调用 underflow() 之前还是之后?不管怎样,可以这么说,我觉得 g++ “在中途换马”很烦人。此外,即使 general seekoff() 需要使缓冲区指针无效,为什么要等同于 ftell()?
谁能指出导致这种行为变化的实现者之间的讨论线索?您是否简要描述了所涉及的选择和权衡?
显然我真的不知道我在做什么。我正在尝试确定是否有一种方法(无论多么不可移植)在偏移量为 0 且 seekdir 为 ios::cur 的情况下绕过失效。我想到了以下 hack,直接访问 filebuf 数据成员 _M_file(这只想在我的机器上使用 3.4.4 版本进行编译):
int sc(0);
filebuf::pos_type my_filebuf::seekoff(
off_type off,
ios_base::seekdir way,
ios_base::openmode mode
)
{
if ((off == 0) && (way == ios::cur))
{
FILE *file =_M_file.file();
pos_type pos = pos_type(ftell(file));
sc++;
if ((sc % 100) == 0) {
cerr << "POS IS " << pos << endl;
}
return pos;
}
return filebuf::seekoff(off, way, mode);
}
但是,每百次 seekoff 尝试打印出位置的诊断每次都会产生 8192。嗯?由于这是 filebuf 本身的 FILE *
成员,我希望它的文件位置指针与任何 同步filebuf 进行的 underflow() 调用。为什么我错了?
首先,让我强调一下,我明白我帖子的后半部分是关于非可移植黑客的。仍然,不了解这里的细节。我试着打电话
pos_type pos = _M_file.seekoff(0,ios::cur);
相反,这愉快地通过示例文件进行,而不是卡在 8192。
在我的公司内部,我们已经制定了一些解决方法来降低性能影响,我们可以忍受它。
在外部,David Krauss 提交了一份针对 GNU 的 libstdc++ 流的 bug,最近,Paolo Carlini checkin 了一个修复程序。一致认为,不良行为在标准范围内,但对于我描述的边缘情况有合理的修复。
非常感谢 StackOverflow、David Krauss、Paolo Carlini 和所有 GNU 开发人员!
最佳答案
seekoff
的要求当然令人困惑,但 seekoff(0, ios::cur)
应该是一种不同步任何内容的特殊情况。所以这可能被认为是一个错误。
它仍然发生在 GCC 4.2.1 和 4.5 中......
问题是 (0, ios::cur)
在 _M_seek
中不是特例,seekoff
用来调用 fseek
获取其返回值。只要成功,_M_seek
就会无条件调用 _M_set_buffer(-1);
,这可以预见会使内部缓冲区无效。下一个读取操作导致下溢
。
Found the diff! 查看更改 -473,41 +486,26
。评论是
(seekoff): Simplify, set _M_reading, _M_writing to false, call
_M_set_buffer(-1) ('uncommitted').
所以这不是为了修复错误。
关于c++ - 解释 GNU C++ filebuf::underflow() 与 filebuf::seekoff() 交互的变化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3678010/
我公司的产品运行在许多合格的 Linux 硬件/软件配置上。从历史上看,使用的编译器是 GNU C++。出于本文的目的,让我们将版本 3.2.3 视为基线,因为我们的软件在该版本中“按预期工作”。 随
typedef struct { char c[20]; int i; } header; void foo(std::string s) { std::ifstream ifs(s.c_
我有一个使用 STLPort 5.2.1 的 Visual Studio 2008 C++ 03 应用程序,我想在其中使用自定义 std::filebuf执行。例如: class MyFileBuf
我正在尝试将我的代码从 std::fstream 转换为 std::filebuf: fstream版本(原版): std::ifstream stream(file); stream.seekg(0
这是代码: #include #include #include int main() { { std::filebuf f; f.open("test.
我有一些代码使用 std::ifstream 从文件中读取,但不使用 std::ifstream 提供的任何格式化功能。它基本上做这样的事情: std::ifstream in; in.open("e
我正在修复一些使用旧式 iostream 库的相当旧的 C++ 代码,我遇到了以下非编译代码行: ::ofstream ofile; ofile.open("filename", ios::trunc
我如何设置一个新的字符数组作为fstream的filebuf的缓冲区,filebuf中有一个函数(setbuf)但它是 protected 。在网上搜索时,有些网站提到 fstream::setbuf
我正在尝试制作一个自定义的 std::fstream,它会在读取时对数据进行编码/解码。 template class _filebuf : public std::filebuf { public
请检查以下代码: #include #include #include int main() { char mybuffer[512]; std::filebuf* optr =
我创建了一个空文件,我正在尝试调整它的大小。除了打开模式外,我的调整大小和创建代码非常相似。初始创建按预期工作。调整大小的代码执行得很好,但文件大小调整没有反射(reflect)出来。 这是我的代码:
带有 ifstream我们可以将整个文件输出到cout像这样: std::ifstream foo("testfile"); std::cout #include #include int ma
如果使用 std::filebuf,是否有等同于以下函数的函数? : std::ifstream::eof std::ifstream::fail std::ifstream::tellg 如果是,是
在尝试将一段 C++ 代码从 MSWindows 移植到 Linux (Mint10) 时,我偶然发现了一个奇怪的问题。我发现硬编码文件名中有一个小错字:尾随空格字符 (\x20)。 该代码在 Win
我是一名优秀的程序员,十分优秀!