填充std :: vector时分配错误

时间:2013-10-12 19:17:25

标签: c++ file-io vector

我正在读取三个大型二进制文件(每个c.180Mb)到std :: vector中,如下所示:

m_ifStream.open("myfile.dat", std::ios::binary | std::ios::in);

if (m_ifStream)
{
    //Obtain input stream length
    m_ifStream.seekg (0, ios::end);
    streamLength = (size_t)(m_ifStream.tellg());
    m_ifStream.seekg (0, ios::beg);

    //Reserve doesn't work around the problem, may be more efficient though...
    //m_buffer = new vector<unsigned char>();
    //m_buffer->reserve(streamLength);

    //Next line sometimes results in bad_alloc when reading a large file
    m_buffer = new vector<unsigned char>((std::istreambuf_iterator<char>(m_ifStream)), (std::istreambuf_iterator<char>()));
}

填充向量的调用失败,抛出“错误分配”异常。

阅读第一个文件时,人口有时会失败;在其他时候它在第二个或第三个失败。我正在使用Visual Studio 2010并将我的代码编译为32位,应该能够解决高达2Gb的问题。我在一台16Gb RAM的机器上运行,至少有10Gb空闲,因此缺少可用内存不是问题。调试和发布配置中都会发生错误。

使用reserve预分配内存无济于事。

向量的max_size属性返回2 ^ 32,因此它似乎不是容器中的限制。

代码很好,有大量小文件,组合大小&gt; 180Mb,让我认为我的代码正在触及边界。

是否有可接受的方法从大输入文件填充向量?我想避免迭代文件中的每个字节,并且认为使用istreambuf_iterator将针对此类操作进行优化。

3 个答案:

答案 0 :(得分:2)

如果您希望拨打reserve()对实际阅读产生任何影响,则应创建临时std::vector<unsigned char>并将此临时分配给目标向量。相反,你使用像

这样的东西
m_buffer->assign(std::istreambuf_iterator<char>(m_ifStream),
                 std::istreambuf_iterator<char>());

在没有保留的情况下读取文件可能会以某种方式破坏你的内存,但是我不希望程序内存耗尽像你这样的小文件(几英寸的文件可以被认为很大; 160MB不是真的很大。如果你知道文件的大小,你最好不要使用read()成员阅读文件,但是:

m_buffer->resize(streamLength);
m_ifStream.read(reinterpret_cast<char*>(m_buffer->data()), streamLength);

我个人猜测std::bad_alloc例外实际上是由于确定文件大小时出错。例如,我认为std::size_t不一定足以容纳std::streamsize。此外,没有尝试验证任何这些操作是否成功,如果无法打开流,seekg()将返回pos_type(-1),这将转换为相当大的std::size_t

答案 1 :(得分:1)

你正在做更多的工作并分配比你需要的更多的内存。

首先删除指针,它什么都不添加

vector<char> m_buffer;

然后调整resize(不保留)到正确的大小

m_buffer.resize(streamLength);

如果你的内存耗尽,就会发生这种情况。

最后将数据直接读入矢量,不要使用streambuf_iterator,谁知道幕后是什么

m_ifStream.read(&m_buffer[0], streamLength);

这里的主要好处是你只分配一个向量(你的代码有两个向量,其中一个被复制到另一个向上),其次你已经删除了所有的绒毛,只剩下两个基本操作,分配记忆,读取文件。

答案 2 :(得分:0)

m_buffer = new vector<unsigned char>();
m_buffer->reserve(streamLength);

//Next line sometimes results in bad_alloc when reading a large file
*m_buffer = vector<unsigned char>((std::istreambuf_iterator<char>(m_ifStream)), (std::istreambuf_iterator<char>()));

首先让我感到震惊的是你覆盖了vector已经预先分配的区域。如果你创建一个新的向量来覆盖那个向量,那么做“保留”显然没有意义。它只是意味着你必须为这些相对较大的向量提供空间。

我首先要将m_buffer更改为不是指向vector的指针 - 这样,你不必调用new vector<unsigned char> - 它的目的很少就是有一个指向vector的指针[如果你有一个不包含任何内容的向量,那么你最多可以节省大约16个字节。

然后删除reserve。看看情况如何。