gpt4 book ai didi

c++ - 来自 boost::iostreams::copy() 的异常

转载 作者:太空宇宙 更新时间:2023-11-04 12:24:39 24 4
gpt4 key购买 nike

在下面的代码中,我有一个损坏的“hello.bz2”,它有超出 EOF 的杂散字符。

有没有办法让 boost::iostreams::copy() 调用抛出?

#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);
}

编辑:请忽略迄今为止最受关注的行;结束语。请假设使用损坏的 bzip2 文件。我使用“EOF”提示我在文件上运行 bzcat 时遇到的错误

bzcat hello.bz2
hello world

bzcat: hello.bz2: trailing garbage after EOF ignored

最佳答案

研究

std::ios_base::failure 是“作为异常抛出的所有对象类型的基类,由 Iostreams 库中的函数报告在流缓冲区操作期间检测到的错误。”

Looking在 boost 文档中:

class bzip2_error : public std::ios_base::failure {
public:
bzip2_error(int error);
int error() const;
};

bzip2_error 是使用 bzip2 过滤器时抛出的特定异常,它继承自 std::ios_base::failure。如您所见,它是通过传入一个表示错误代码的整数来构造的。它还有一个方法 error(),它返回构造时使用的错误代码。
文档列出 bzip2 错误代码如下:

  • data_error - 表示压缩数据流已损坏。等于 BZ_DATA_ERROR。
  • data_error_magic - 表示压缩数据流不是以“魔法”序列“B”“Z”“h”开头。等于 BZ_DATA_ERROR_MAGIC。
  • config_error - 表示 libbzip2 针对当前平台的配置不正确。等于 BZ_CONFIG_ERROR。

代码

编辑我还想澄清 boost::iostreams::copy() 不会是这里抛出异常的那个,而是 bzip2 过滤器。只有 iostream 或过滤器会抛出异常,复制只是使用 iostream/filter 可能会导致 iostream/filter 抛出异常。

**编辑2 **正如您所料,问题似乎出在 bzip2_decompressor_impl 上。当 bz2 文件为空时,我已经复制了无休止的旋转循环。我花了一点时间弄清楚如何构建 boost 并链接到 bzip2、zlib 和 iostreams 库,看看我是否可以复制您的结果。

g++ test.cpp -lz -lbz2 boostinstall/boost/bin.v2/libs/iostreams/build/darwin-4.2.1/release/link-static/threading-multi/libboost_iostreams.a -Lboostinstall/boost/bin.v2/libs/ -Iboost/include/boost-1_42 -g

测试.cpp:

#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;

try {
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);
}
catch(const bzip2_error& exception) {
int error = exception.error();

if(error == boost::iostreams::bzip2::data_error) {
// compressed data stream is corrupted
cout << "compressed data stream is corrupted";
}
else if(error == boost::iostreams::bzip2::data_error_magic)
{
// compressed data stream does not begin with the 'magic' sequence 'B' 'Z' 'h'
cout << "compressed data stream does not begin with the 'magic' sequence 'B' 'Z' 'h'";
}
else if(boost::iostreams::bzip2::config_error) {
// libbzip2 has been improperly configured for the current platform
cout << "libbzip2 has been improperly configured for the current platform";
}
}
}

调试:

gdb a.out
(gdb) b bzip2.hpp:344

在 symmetric.hpp:109 中有一个驱动 bzip2 解压缩的循环:

        while (true)
{
// Invoke filter if there are unconsumed characters in buffer or if
// filter must be flushed.
bool flush = status == f_eof;
if (buf.ptr() != buf.eptr() || flush) {
const char_type* next = buf.ptr();
bool done =
!filter().filter(next, buf.eptr(), next_s, end_s, flush);
buf.ptr() = buf.data() + (next - buf.data());
if (done)
return detail::check_eof(
static_cast<std::streamsize>(next_s - s)
);
}

// If no more characters are available without blocking, or
// if read request has been satisfied, return.
if ( (status == f_would_block && buf.ptr() == buf.eptr()) ||
next_s == end_s )
{
return static_cast<std::streamsize>(next_s - s);
}

// Fill buffer.
if (status == f_good)
status = fill(src);
}

bzip2_decompressor_impl 的过滤方法 bzip2.hpp:344 在 symmetric.hpp:117 上被调用:

template<typename Alloc>
bool bzip2_decompressor_impl<Alloc>::filter
( const char*& src_begin, const char* src_end,
char*& dest_begin, char* dest_end, bool /* flush */ )
{
if (!ready())
init();
if (eof_)
return false;
before(src_begin, src_end, dest_begin, dest_end);
int result = decompress();
after(src_begin, dest_begin);
bzip2_error::check BOOST_PREVENT_MACRO_SUBSTITUTION(result);
return !(eof_ = result == bzip2::stream_end);
}

我认为问题很简单,bzip2_decompressor_impl 的 eof_ 标志永远不会设置。除非它假设以某种我不理解的神奇方式发生,否则它归 bzip2_decompressor_impl 类所有,并且它只会被设置为 false。所以当我们这样做时:

cat /dev/null > hello.bz2

我们得到一个永不结束的旋转循环,当遇到 EOF 时我们不会中断。这当然是一个错误,因为其他程序(如 vim)打开以类似方式创建的文本文件没有问题。但是,当 bz2 文件“损坏”时,我能够让过滤器抛出:

echo "other corrupt" > hello.bz2
./a.out
compressed data stream does not begin with the 'magic' sequence 'B' 'Z' 'h'

有时您不得不对开源代码持保留态度。您的 bz2 更有可能被损坏并正确抛出。但是,/dev/null 的情况是一个严重的错误。我们应该将其提交给 boost 开发人员,以便他们修复它。

关于c++ - 来自 boost::iostreams::copy() 的异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3167109/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com