c ++ std :: bad_alloc при загрузке 1,9 миллиона строк файла значений с плавающей запятой - предоставляется исходный код

0

Поэтому у меня есть задание, где я читаю 1,9 миллиона строк значений с плавающей запятой (360 плавающих точек на строку), и мне нужно работать с этими данными. Первоначально у меня было это, и я не уверен, почему сегодня я получаю bad_alloc. Вот мой код. Мне интересно, есть ли что-нибудь, что я могу сделать, чтобы оптимизировать его лучше - я использую векторы, и я надеялся, что мне не придется использовать массивы структур. Я могу просто создать структуру и создать массив структур, и каждая структура будет содержать x, y и массив значений с плавающей запятой. Будет ли это иметь большую значимость?

Я бы очень признателен за любую критику моей реализации и кода. Благодарю!

Реализация

#include "file_parser.hpp"

Parser::Parser(char* fname){
    fileName = fname;
}

/*
*   The function parses a file that was set in the constructor
*   And returns a map of the file
*/
VectorsMap Parser::parseFile(){
    //open file
    fPtr = fopen(fileName, "r");
    total_rows = 0;
    line = (char*)malloc(sizeof(char)*LINE_MAX);

    //parse the file line by line
    while(fgets(line, LINE_MAX, fPtr)){
        //make sure that we do not read an empty line
        if(line[0] != '\0') {
            //send the line to be further parsed
            parseLine(line);
            //increment total rows count
            total_rows++;   
        }
    }
    return vector_points;
}

void Parser::doCleanUp(){
    fclose(fPtr);
    free(line);
    vector_points.clear();
}

/**
*   Parse a line and tokenize it
*   while extracting X and Y points
*   and vectors and put them in a VectorsMap(deifned in file_parser.h)
*/
void Parser::parseLine(char* line){
    //collection of vectors.
    std::vector<float> vectors;
    char* point;

    //grab the x and y tokens
    char* tk1 = strtok(line, ",");
    char* tk2 = strtok(NULL, ",");

    //value for indexing
    int i=0;
    char* tmp;

    //make sure we have two correct x and y points
    if(tk1 == NULL || tk2 == NULL){ return; }

    //convert the tokens to floats
    float x = strtof(tk1, NULL);
    float y = strtof(tk2, NULL);

    //create the x and y pair used to insert vectors into the map
    XYPair pair = XYPair(x, y);

    //tokenize until end of line
    while(point=strtok(NULL, ",")){
        //convert the token to float
        float f_point = strtof(point, NULL);
        //push the float to the vector
        vectors.push_back(f_point);
        i++;
    }
    //insert in the vectormap.
    vector_points.insert(VectorsPair(pair, vectors));
}

int Parser::getTotalRows(){
    return total_rows;
}

Заголовок файла:

//create specific types to make my life easier later on 
typedef std::pair<float, float> XYPair;

typedef std::pair<XYPair, std::vector<float> > VectorsPair;
typedef std::map<XYPair, std::vector<float> > VectorsMap;

class Parser{       
    public:
        //constructor
        Parser(char* fname);
        VectorsMap parseFile();
        int getTotalRows();
        int row_values;
        int total_rows;
        void doCleanUp();
    private:
        //collection of all x y points and their vectors 
        VectorsMap vector_points;
        FILE* fPtr; //file pointer to file to be parsed
        char *line; //line to parse file line by line
        char* fileName; //path/name of file to be parsed

        void parseLine(char* line);
};
  • 1
    «Первоначально у меня это работало, и я не уверен, почему я получаю bad_alloc сегодня» - так что изменилось? Ваш код, ваши структуры, объем входных данных? Вы действительно должны прочитать все это в памяти сразу?
  • 0
    На самом деле ничего не изменилось, вот в чем проблема ... Интересно, зависит ли это от трафика сервера? Мне нужно загрузить весь файл сразу. Система должна быть способна обрабатывать этот файл, загружаемый в память.
Показать ещё 11 комментариев
Теги:
file
pointers
c++11
vector

1 ответ

0
Лучший ответ

Вызов malloc и fopen при вызове parseFile но затем освобождение в отдельной функции чрезвычайно подвержено ошибкам. Если вы звоните parseFile дважды без вызова doCleanup то утечка памяти и дескриптор файла.

Я бы прекратил использовать malloc и strtok.

VectorsMap Parser::parseFile(){
    //open file
    std::ifstream f(fileName);
    total_rows = 0;
    std::string line;

    //parse the file line by line
    while(std::getline(f, line)){
        //make sure that we do not read an empty line
        if(line.size()) {
            //send the line to be further parsed
            parseLine(line);
            //increment total rows count
            total_rows++;   
        }
    }
    return vector_points;
}

А затем parseLine чтобы не использовать ужасную функцию strtok, например, используя Boost.Tokenizer или std::istringstream и std::getline

Также обратите внимание, что вы читаете данные в vector_points затем возвращаете копию, что означает, что вам нужно в два раза больше памяти, используемой набором данных. Вы можете сохранить только одну копию данных, выполнив следующие действия:

return std::move(vector_points);

поэтому данные перемещаются в возвращаемое значение, а не копируются.

  • 0
    это очень хорошие предложения, которые, я думаю, сработают. Спасибо

Ещё вопросы

Сообщество Overcoder
Наверх
Меню