C++ 添加~10000个键后,无序的_图中出现分段错误
当尝试插入到无序的_映射中时,当datact=10736时,会发生分段错误(请参阅调用引发错误的注释行)。请参阅下面的尝试修复 当抛出SIGSEGV时,它将我指向hashtable_policy.h的第764行 输入:数据文件,列1=计数,列2=16个字符串 目的:通过将1-替换不同序列的所有计数相加,对16个字符序列进行聚类。看到的第一个序列是“起源”,通过它可以识别所有的1-取代友元 伪代码:对于文件中的每一行:C++ 添加~10000个键后,无序的_图中出现分段错误,c++,unordered-map,segmentation-fault,C++,Unordered Map,Segmentation Fault,当尝试插入到无序的_映射中时,当datact=10736时,会发生分段错误(请参阅调用引发错误的注释行)。请参阅下面的尝试修复 当抛出SIGSEGV时,它将我指向hashtable_policy.h的第764行 输入:数据文件,列1=计数,列2=16个字符串 目的:通过将1-替换不同序列的所有计数相加,对16个字符序列进行聚类。看到的第一个序列是“起源”,通过它可以识别所有的1-取代友元 伪代码:对于文件中的每一行: 读取计数,读取顺序 如果序列键_值存在于散列“位置”(类型 无序_映射),添加
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括“矩阵h”
使用名称空间std;
int numc2num(char currchar)
{//分别为A、C、T、G返回0,1,2,3
int-outnum;
如果(currchar=='A')
{
outnum=0;
}
else if(currchar=='C')
{
outnum=1;
}
else if(currchar=='T')
{
outnum=2;
}
其他的
{
outnum=3;
}
返回outnum;
}
int main(int argc,char*argv[])
{
//命令行参数
//arg1=文件名,arg2=条形码序列长度,arg3=允许不匹配
//输入处理
//文件格式:第1列|第2列
//计数|序列[int |字符串]
字符串文件名;
串漏斗;
//定义查找矩阵;rows=ACTG,cols=ACTG,不带row元素
矩阵子_查找(4,3);
子_查找[0][0]=“C”;
子_查找[0][1]=“T”;
子_查找[0][2]=“G”;
子_查找[1][0]=“A”;
sub_lookup[1][1]=“T”;
sub_lookup[1][2]=“G”;
子_查找[2][0]=“A”;
sub_lookup[2][1]=“C”;
sub_lookup[2][2]=“G”;
子_查找[3][0]=“A”;
sub_lookup[3][1]=“C”;
sub_lookup[3][2]=“T”;
int L,k;
int j=0;
常量int buffersize=10000;
int currentsize=缓冲区大小;
int-datact=0;
int currchar;
向量ctarr(缓冲区大小);
向量seqarr(buffersize);
filename=argv[1];
L=atoi(argv[2]);
k=atoi(argv[3]);
无符号整数sct;
int substrlen;
字符串序列,textct;
ifstream seqfile(filename.c_str());
//地图位置;
无序的地图位置;
if(seqfile.is_open())
{
getline(seqfile,textct,'\n');
而(textct!=“”)
{
sct=atoi(textct.c_str());
substrlen=textct.length();
//调用vector::resize()时,指向vector
元素的指针可能无效
。这是因为为了找到适合新大小的连续内存块,可能必须移动整个数据。换句话说,只要调用resize
,所有位置的数据就会突然变成无用的垃圾
可能的解决办法:
- 让
location
将ctarr
中所需元素的索引存储为其值,而不是指针。(这肯定不会改变程序的语义。)
- 让
location
存储实际的unsigned int
值,而不是指针。根据您的程序逻辑以及更改和访问此数据的方式,这可能不是您想要的
还要注意的是,尽管segfault出现在哈希表_policy.h
中,但此bug与无序映射
(或向量
)的实现无关-没有读取向量::resize()
;-)的引用完全是您的错。(“迭代器有效性”部分)
关于您的代码,我注意到的另一件事是您使用操作符[]
访问向量
元素。这将禁用越界检查。如果我在代码中遇到与您类似的错误(很难追溯,因为它发生在远离错误代码的地方),我的第一步行动是将操作符[]
替换为向量::at()
(实际上,我总是从at()
开始,并且只有在我能够毫无疑问地证明边界检查是这一特定目的的性能瓶颈时,才切换)。这对解决您的问题没有帮助,但在发现错误方面通常是非常宝贵的帮助。调用vector::resize()时,指向vector
元素的指针可能会失效
。这是因为为了找到适合新大小的连续内存块,可能必须移动整个数据。换句话说,只要调用resize
,所有位置的数据就会突然变成无用的垃圾
可能的解决办法:
- 让
location
将ctarr
中所需元素的索引存储为其值,而不是指针。(这肯定不会改变程序的语义。)
- 让
location
存储实际的unsigned int
值,而不是指针。根据您的程序逻辑以及更改和访问此数据的方式,这可能不是您想要的
还要注意的是,尽管segfault出现在哈希表_policy.h
中,但此bug与无序映射
(或向量
)的实现无关-没有读取向量::resize()
;-)的引用完全是您的错。(“迭代器有效性”部分)
关于您的代码,我注意到的另一件事是,您使用操作符[]
访问向量
元素。这将禁用越界检查。如果我在代码中遇到与您类似的错误(因为它发生了,所以很难追溯)
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <cmath>
#include <vector>
#include <unordered_map>
#include <map>
#include "matrix.h"
using namespace std;
int nuc2num(char currchar)
{ // returns 0,1,2,3 for A,C,T,G respectively
int outnum;
if (currchar=='A')
{
outnum=0;
}
else if (currchar=='C')
{
outnum=1;
}
else if (currchar=='T')
{
outnum=2;
}
else
{
outnum=3;
}
return outnum;
}
int main(int argc, char* argv[])
{
//command line arguments
// arg1=filename, arg2=barcode sequence length, arg3=#mismatches permitted
//input handling
// file format: column 1 | column 2
// counts | sequence [int | string]
string filename;
string funnelstring;
// define lookup matrix; rows=ACTG, cols = ACTG without row element
Matrix <char> sub_lookup(4,3);
sub_lookup[0][0] = 'C';
sub_lookup[0][1] = 'T';
sub_lookup[0][2] = 'G';
sub_lookup[1][0] = 'A';
sub_lookup[1][1] = 'T';
sub_lookup[1][2] = 'G';
sub_lookup[2][0] = 'A';
sub_lookup[2][1] = 'C';
sub_lookup[2][2] = 'G';
sub_lookup[3][0] = 'A';
sub_lookup[3][1] = 'C';
sub_lookup[3][2] = 'T';
int L,k;
int j=0;
const int buffersize=10000;
int currentsize=buffersize;
int datact=0;
int currchar;
vector <unsigned int> ctarr(buffersize);
vector <string> seqarr(buffersize);
filename=argv[1];
L=atoi(argv[2]);
k=atoi(argv[3]);
unsigned int sct;
int substrlen;
string sequence,textct;
ifstream seqfile (filename.c_str());
//map <string,unsigned int*> location;
unordered_map <string,unsigned int*> location;
if (seqfile.is_open())
{
getline(seqfile,textct,'\n');
while (textct != "")
{
sct=atoi(textct.c_str());
substrlen=textct.length();
//cout << textct << endl;
sequence=textct.substr(substrlen-L,L);
//cout << sequence << endl;
//is there an associated guy?
if (location.find(sequence) != location.end()) //just asks whether this key has been assigned
{ //there's a value in the region
*location[sequence]+=sct;
}
else
{ //no value in region, make a footprint
ctarr[datact]=sct;
seqarr[datact]=sequence;
location[sequence]=&ctarr[datact]; //assign current key to point to data count
//assign k substitution "funnel" region to point to this count as well
for (j=0; j<L; j++)
{
funnelstring=sequence;
currchar = nuc2num(sequence[j]);
if (datact==10736 && j==13)
{
cout << "here" << endl;
cout << sequence << endl;
}
for (k=0; k<3; k++)
{
funnelstring[j]=sub_lookup[currchar][k];
// if (datact==10736 && j==13)
// {
// cout << funnelstring << endl;
// cout << location.max_size() << " | " << location.size() << endl;
// string asdf;
// asdf="AAAAAAAAAAAAAAAA";
// location[asdf]=&ctarr[datact]; //still segfaults
// }
if (location.find(funnelstring) == location.end()) // asks whether this key has been assigned
{ //this region is not assigned to another funnel
location[funnelstring]=&ctarr[datact]; //LINE THAT CAUSES SIGSEGV
}
}
}
datact++;
cout << datact << endl;
if (datact>=currentsize)
{
ctarr.resize(currentsize+buffersize);
seqarr.resize(currentsize+buffersize);
currentsize+=buffersize;
}
}
getline(seqfile,textct,'\n');
}
seqfile.close();
}