我正在读取三个大型二进制文件(每个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
将针对此类操作进行优化。
答案 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
。看看情况如何。