Ошибка при чтении большого файла с помощью ifstream на 64-битном Debian - PullRequest
0 голосов
/ 18 февраля 2012

Я пытаюсь прочитать большой файл (~ 5 ГБ), используя ifstream в C ++.Так как я на 64-битной ОС, я подумал, что это не должно быть проблемой.Тем не менее, я получил Segfault.Все отлично работает с небольшими файлами, так что я уверен, что проблема именно в этом.

Я использую 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);
}

Сегфоут находится в строке is.read для i = 187664.T float, и я читаю dim = 1000 float одновременно.Когда происходит segfault, i * stride становится намного меньше размера, поэтому я не пробегаю до конца файла.

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 ]

1 голос
/ 18 февраля 2012

Я не знаю, является ли это ошибкой, но этот код очень похож на 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, он гарантированно сможет удерживатьразмер объекта, включая массивы.

0 голосов
/ 23 сентября 2012

Я думаю, вы должны использовать _ftelli64 и т. Д. ..., чтобы иметь правильный размер вашего файла, и использовать long long (или _int64) переменные для управления им. Но это библиотека Си. Я не нахожу, как использовать ifstream с таким большим файлом (на самом деле> 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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...