【发布时间】:2013-11-26 12:16:07
【问题描述】:
我在尝试解析大文本文件时遇到分段错误。该文件包含 91 529 个 mRNA 转录本和有关这些转录本的详细信息。我创建了一个 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 GB,由大约 44 000 000 行组成,因此对于如何提高效率的任何提示也将不胜感激。
【问题讨论】:
-
where 在您显示的代码中它是否因分段错误而停止?使用您选择的调试器(gdb、visual studio)运行程序,并报告它失败的行号。还有,那条线 1829/1830 有什么特别之处吗?也许这是根据解析代码似乎第一次出现的一种线型?
-
你的盒子有多少内存?您可能内存不足,其中一个分配失败并返回 NULL。
-
为什么最后用
transcript = new RefSeqTranscript复制?仅使用堆栈上的对象,例如RefSeqTranscript transcript。 -
感谢您的帮助,SB 的回答解决了问题。也就是说,我需要大量阅读堆和堆栈以及何时/如何使用它们。
-
除非您需要对象超过范围,否则请使用堆栈。如果需要
std::shared_ptr和make_shared<>,或者shared_array等......然后,如果你不能使用以前的解决方案,请使用原始指针和new。
标签: c++ segmentation-fault string-parsing