Разбор текстового файла в список дает ошибку сегментации

0

Я получаю ошибку сегментации при попытке проанализировать большой текстовый файл. Файл содержит 91 529 транскриптов мРНК и подробности об этих транскриптах. Я создал объект RefSeqTranscript, который будет принимать эти данные. Когда я разбираю файл, я создаю список этих объектов и начинаю вводить данные в эти списки. Он отлично работает для первых расшифровок 1829 года, а затем падает с ошибкой сегментации. Метод, который я запускаю:

void TranscriptGBFFParser::ParseFile(list<RefSeqTranscript> &transcripts, const char* filepath)
{
    cout << "Parsing " << filepath << "..." << endl;

    ifstream infile;
    infile.open(filepath);

    int num = 0;
    RefSeqTranscript *transcript = new RefSeqTranscript();
    for(string line; getline(infile, line); )
    {
        in.clear();
        in.str(line);

        if (boost::starts_with(line, "LOCUS"))
        {
            if((*transcript).transcriptRefSeqAcc.size() > 0)
            {           
                cout << (*transcript).transcriptRefSeqAcc << ":" << (*transcript).gi << ":" << (*transcript).gene.geneName << ":" << ++num << endl; 

                transcripts.push_back(*transcript); 
                delete transcript;

                RefSeqTranscript *transcript = new RefSeqTranscript();  

            }   
        }
        else if (boost::starts_with(line, "     var"))
        {
            TranscriptVariation variant;
            (*transcript).variations.push_back(variant);            
        }
        //Store the definition of the transcript in the description attribute
        else if (boost::starts_with(line, "DEFINITION"))
        {           
            (*transcript).description = line.substr(12);

            for(line; getline(infile, line); )
            {
                if(boost::starts_with(line, "ACCESSION   "))
                    break;

                (*transcript).description += line.substr(12);
            }       
        }
        //The accession number and GI number are obtained from the VERSION line
        else if (boost::starts_with(line, "VERSION"))
        {
            string versions = line.substr(12);
            vector<string> strs;
            boost::split(strs, versions, boost::is_any_of( " GI:" ), boost::token_compress_on);
            boost::trim_left(strs[0]);

            (*transcript).transcriptRefSeqAcc = strs[0];
            (*transcript).gi = atoi(strs[1].c_str());
        }
        //Gene information is obtained from the "gene" sections of each transcript
        else if (boost::starts_with(line, "     gene"))
        {           
            for(line; getline(infile, line); )
            {
                if(boost::starts_with(line.substr(21), "/gene="))
                {
                    Gene *gene = new Gene();

                    string name = line.substr(27);
                    Utilities::trim(name, '\"');

                    (*gene).geneName = name;

                    (*transcript).gene = *gene;

                    delete gene;
                    break;
                }
            }
            (*transcript).gene.geneID = 0;      
        }
        else if (boost::starts_with(line, "     CDS"))
        {
            (*transcript).proteinRefSeqAcc = "";            
        }
        else if (boost::starts_with(line, "ORIGIN"))
        {
            (*transcript).sequence = "";            
        }       
    }

    cout << (*transcript).transcriptRefSeqAcc << ":" << (*transcript).gi << ":" << (*transcript).gene.geneName << endl;

    transcripts.push_back(*transcript); 
    delete transcript;          

    cout << "No. transcripts: " << transcripts.size() << endl;
    cout << flush;

    infile.close();

    cout << "Finished parsing " << filepath << "." << endl; 
}

Я новичок в C++ и не очень хорошо понимаю, как работать с указателями и т.д., Поэтому я предполагаю, что, возможно, я сделал что-то не так. Я не понимаю, почему это работает почти для 2000 объектов, прежде чем вырезать.

Файл, который я обрабатываю, составляет 2,1 ГБ и состоит из 44 000 000 строк, поэтому любые советы о том, как повысить эффективность, также будут высоко оценены.

  • 0
    где в коде, который вы показываете, он останавливается с ошибкой сегментации? запустите программу с выбранным вами отладчиком (gdb, visual studio) и сообщите номер строки, на которой она не работает. Кроме того, есть что-то особенное в этой строке 1829/1830? может быть, это первый случай появления одного из типов строк в соответствии с кодом синтаксического анализа?
  • 0
    сколько оперативной памяти у вас на коробке? Возможно, вам не хватает памяти, и одно из распределений завершается с ошибкой и возвращает NULL.
Показать ещё 4 комментария
Теги:
string-parsing
segmentation-fault

2 ответа

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

Это, вероятно, не единственный ответ, но у вас есть утечка...

    if (boost::starts_with(line, "LOCUS"))
    {
        if((*transcript).transcriptRefSeqAcc.size() > 0)
        {           
            cout << (*transcript).transcriptRefSeqAcc << ":" << (*transcript).gi << ":" << (*transcript).gene.geneName << ":" << ++num << endl; 

            transcripts.push_back(*transcript); 
            delete transcript;
            // LEAK!
            RefSeqTranscript *transcript = new RefSeqTranscript();  

        }   
    }

Вы, вероятно, имеете в виду:

transcript = new RefSeqTranscript();

  • 0
    Это исправлено, спасибо !!!!! :)
0

Трудно сказать что-либо конкретное, если вы не предоставите более подробную информацию:

  • Какая линия разбилась?
  • Вам действительно нужны все эти стенограммы одновременно?

Но я бы предложил вам пару улучшений:

  • Не используйте указатель (или, по крайней мере, использовать интеллектуальный указатель) для RefSeqTranscript *transcript;
  • Не используйте указатель для Gene *gene;
  • Как правило, не используйте указатели, если они вам не нужны;

И у вас есть ошибка здесь:

   delete transcript;

   RefSeqTranscript *transcript = new RefSeqTranscript(); 

Поскольку вы объявили транскрипт вне тела цикла, здесь вы спрячете его с новой переменной с тем же именем. Это вызывает утечку памяти, и, кроме того, вы удаляете внешний транскрипт и ничего не заменяете. Итак, вы, вероятно, получите крах на следующей итерации.

  • 0
    Спасибо, ошибка, которую вы указали, решила проблему. В чем причина неиспользования указателей?
  • 0
    @DavidBrown Каждый раз, когда вы используете указатель, существует потенциальная утечка памяти. Когда вы используете объект, временем жизни которого управляет компилятор, у вас даже нет возможности создать утечку памяти.
Показать ещё 1 комментарий

Ещё вопросы

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