Segfault在64位Debian上使用ifstream读取大文件

时间:2012-02-18 14:24:12

标签: c++ 64-bit g++ ifstream

我试图在C ++中使用ifstream读取一个大文件(~5GB)。 由于我是64位操作系统,我认为这应该不是问题。 不过,我得到了一个段错误。一切都运行得很好,文件较小, 所以我很确定这就是问题所在。

我正在使用g ++(4.4.5-8)和libstdc ++ 6(4.4.5-8)。

感谢。

代码如下所示:

void load (const std::string &path, int _dim, int skip = 0, int gap = 0) {
    std::ifstream is(path.c_str(), std::ios::binary);
    BOOST_VERIFY(is);
    is.seekg(0, std::ios::end);
    size_t size = is.tellg();
    size -= skip;
    long int line = sizeof(float) * _dim + gap;
    BOOST_VERIFY(size % line == 0);
    long int _N =  size / line;
    reset(_dim, _N);
    is.seekg(skip, std::ios::beg);
    char *off = dims;
    for (long int i = 0; i < N; ++i) {
        is.read(off, sizeof(T) * dim);
        is.seekg(gap, std::ios::cur);
        off += stride;
    }
    BOOST_VERIFY(is);
}

对于i = 187664,段错误位于is.read行。 T是浮动的,我一次读的是dim = 1000浮点数。 当发生段错误时,i *步幅小于大小,所以我没有超过文件的末尾。

dims在这里分配

void reset (int _dim, int _N)
{
    BOOST_ASSERT((ALIGN % sizeof(T)) == 0);
    dim = _dim;
    N = _N;
    stride = dim * sizeof(T) + ALIGN - 1;
    stride = stride / ALIGN * ALIGN;
    if (dims != NULL) delete[] dims;
    dims = (char *)memalign(ALIGN, N * stride); 
    std::fill(dims, dims + N * stride, 0);
}

2 个答案:

答案 0 :(得分:1)

我不知道这是不是错误,但是这段代码看起来非常像C并且有很多机会泄漏。任何方式尝试改变

void reset (int _dim, int _N)

void reset (size_t dim, size_t _N)
//I would avoid using leading underscores that is usually used to identify elements of the standard library.

当你处理内存中某些东西的大小或索引时总是使用size_t,它保证能够保持包括数组在内的对象的最大大小。

答案 1 :(得分:0)

我认为您必须使用_ftelli64等...来获得正确的文件大小,并使用long long(或_int64)变量来管理它。但它是C库。我没有找到如何使用ifstream这么大的文件(实际上&gt; 2Go)。你找到了路吗?

PS:在您的情况下size_t没问题,但我不确定32位软件是否正常。我确定64位是可以的。

int main()
{
    string name="tstFile.bin";
    FILE *inFile,*inFile2;
    fopen_s(&inFile,name.c_str(),"rb"); 
    if (!inFile)
    {
        cout<<"\r\n***error -> File not found\r\n";
        return 0;
    }

    _fseeki64 (inFile,0L,SEEK_END);
    long long fileLength = _ftelli64(inFile); 
    _fseeki64 (inFile,0L,SEEK_SET);

    cout<<"file lg : "<<fileLength<<endl;
    return 1;
}