Я получаю ошибку сегментации при попытке проанализировать большой текстовый файл. Файл содержит 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 строк, поэтому любые советы о том, как повысить эффективность, также будут высоко оценены.
Это, вероятно, не единственный ответ, но у вас есть утечка...
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();
Трудно сказать что-либо конкретное, если вы не предоставите более подробную информацию:
Но я бы предложил вам пару улучшений:
RefSeqTranscript *transcript
;Gene *gene
;И у вас есть ошибка здесь:
delete transcript;
RefSeqTranscript *transcript = new RefSeqTranscript();
Поскольку вы объявили транскрипт вне тела цикла, здесь вы спрячете его с новой переменной с тем же именем. Это вызывает утечку памяти, и, кроме того, вы удаляете внешний транскрипт и ничего не заменяете. Итак, вы, вероятно, получите крах на следующей итерации.