boost::iostreams::copy() 的异常
在下面的代码中,我有一个损坏的“hello.bz2”,其中包含超出 EOF 的杂散字符。
有没有办法让 boost::iostreams::copy() 调用 throw ?
#include <fstream>
#include <iostream>
#include <boost/iostreams/filtering_streambuf.hpp>
#include <boost/iostreams/copy.hpp>
#include <boost/iostreams/filter/bzip2.hpp>
int main()
{
using namespace std;
using namespace boost::iostreams;
ifstream file("hello.bz2", ios_base::in | ios_base::binary);
filtering_streambuf<input> in;
in.push(bzip2_decompressor());
in.push(file);
boost::iostreams::copy(in, cout);
}
编辑: 请忽略目前为止最受关注的那一行; EOF。请假设使用损坏的 bzip2 文件。 我使用“EOF”提示在文件上运行 bzcat 时出现的错误
bzcat hello.bz2
hello world
bzcat: hello.bz2: trailing garbage after EOF ignored
In the below code, I have a corrupt "hello.bz2" which has stray characters beyond the EOF.
Is there a way to make the boost::iostreams::copy() call to throw ?
#include <fstream>
#include <iostream>
#include <boost/iostreams/filtering_streambuf.hpp>
#include <boost/iostreams/copy.hpp>
#include <boost/iostreams/filter/bzip2.hpp>
int main()
{
using namespace std;
using namespace boost::iostreams;
ifstream file("hello.bz2", ios_base::in | ios_base::binary);
filtering_streambuf<input> in;
in.push(bzip2_decompressor());
in.push(file);
boost::iostreams::copy(in, cout);
}
EDIT:
Please ignore the line that is so far attracted most attention; the EOF. Please assume working with a corrupted bzip2 file.
I used "EOF" suggesting the error I got when I run bzcat on the file
bzcat hello.bz2
hello world
bzcat: hello.bz2: trailing garbage after EOF ignored
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
研究
std::ios_base::failure 是“Iostreams 库中的函数作为异常抛出的所有对象类型的基类,用于报告在流缓冲区操作期间检测到的错误”。
查看 boost 文档:
bzip2_error是使用bzip2过滤器时抛出的特定异常,它继承自std::ios_base::failure。正如您所看到的,它是通过传入表示错误代码的整数来构造的。它还有一个方法error(),它返回构造它所用的错误代码。
文档列出了 bzip2 错误代码,如下所示:
代码
编辑
我还想澄清一下,boost::iostreams::copy() 不会是这里抛出异常的那个,而是 bzip2 过滤器。只有 iostream 或过滤器会抛出异常,仅复制使用 iostream/filter 可能会导致 iostream/filter 抛出异常。
**编辑2 **
正如您所料,问题似乎出在 bzip2_decompressor_impl 上。当 bz2 文件为空时,我复制了无限旋转循环。我花了一些时间才弄清楚如何构建 boost 并与 bzip2、zlib 和 iostreams 库链接,看看是否可以复制您的结果。
test.cpp:
调试:
在 symmetry.hpp:109 中有一个驱动 bzip2 解压缩的循环:在
symmetry.hpp:117 上调用 bzip2_decompressor_impl 的过滤方法 bzip2.hpp:344 :
我认为问题很简单,bzip2_decompressor_impl 的 eof_ 标志永远不会被设置。除非它以某种我不明白的神奇方式发生,否则它由 bzip2_decompressor_impl 类拥有,并且只会被设置为 false。因此,当我们这样做时:
我们得到一个永远不会结束的旋转循环,当遇到 EOF 时我们不会中断。这肯定是一个错误,因为其他程序(如 vim)打开以类似方式创建的文本文件不会有问题。不过,当 bz2 文件“损坏”时,我能够让过滤器抛出异常:
有时您必须对开源代码持保留态度。您的 bz2 更有可能被损坏并正确抛出。然而,/dev/null 情况是一个严重的错误。我们应该将其提交给 boost 开发人员,以便他们可以修复它。
Research
std::ios_base::failure is the "the base class for the types of all objects thrown as exceptions, by functions in the Iostreams library, to report errors detected during stream buffer operations."
Looking at the boost docs:
bzip2_error is a specific exception thrown when using the bzip2 filter, which inherits from std::ios_base::failure. As you can see, it is constructed by passing in an integer representing the error code. It also has a method error() which returns the error code it was constructed with.
The docs list bzip2 error codes as the following:
Code
EDIT
I also want to clarify that boost::iostreams::copy() will not be the one throwing the exception here, but the bzip2 filter. Only the iostream or filters will throw exceptions, copy just uses the iostream/filter which may cause the iostream/filter to throw an exception.
**EDIT 2 **
It appears the problem is with bzip2_decompressor_impl as you have expected. I have replicated the endless spinning loop when the bz2 file is empty. It took me a little while to figure out how to build boost and link with bzip2, zlib, and iostreams library to see if I could replicate your results.
test.cpp:
debugging:
There is a loop that drives the bzip2's uncompression in symmetric.hpp:109 :
bzip2_decompressor_impl's filter method bzip2.hpp:344 gets called on symmetric.hpp:117 :
I think the problem is simple, the bzip2_decompressor_impl's eof_ flag never gets set. Unless it's suppose to happen in some magic way I don't understand, it's owned by the bzip2_decompressor_impl class and it's only ever being set to false. So when we do this:
We get a spinning loop that never ends, we don't break when an EOF is hit. This is certainly a bug, because other programs (like vim) would have no problem opening a text file created in a similar manner. However I am able to get the filter to throw when the bz2 file is "corrupted":
Sometimes you have to take open source code with a grain of salt. It will be more likely that your bz2's will be corrupted and properly throw. However, the /dev/null case is a serious bug. We should submit it to the boost dev so they can fix it.
如何在文件末尾之外出现杂散字符?
如果您的意思是该文件中包含垃圾数据,那么解压缩算法如何判断该数据是否为垃圾数据,以便能够做出
抛出
的决定?How do you have stray characters beyond the end of the file?
If you mean that the file has garbage data in it, how would the decompression algorithm be able to tell whether or not the data is garbage to be able to make a decision to
throw
?