嘗試插入到unordered_map時,當datact = 10736時發生分段錯誤(請參閱調用引發錯誤的註釋行)。請參閱下面的嘗試修復。添加了〜10000個密鑰後,unordered_map中的段錯誤
當SIGSEGV被拋出它指向我到線764 hashtable_policy.h
的
INPUT:用列1 =計數列2 = 16個字符的字符串
目的數據文件:通過將簇16個字符的序列的所有一起替換不同序列的1次計數。看到的第一個序列是識別其所有1位替換朋友的「原點」。
僞代碼:對於文件中的每一行:
閱讀數,閱讀順序。
如果序列key_value存在於散列'位置'(類型 unordered_map),則添加當前計數;
否則做一個新的key_value,讓它指向這裏的計數,並且 指定所有的1-替換序列也指向這個計數。
代碼:
#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();
}
探索。
- 不要緊添加什麼鍵,當
datact==10736
和j=13
,任何 鍵添加到一個SIGSEGV(unordered_map)定位結果。 - 有問題的代碼行(標有上面的註釋)在之前被調用了很多次,並且運行正常。
- 在同一事件中交換unordered_map以獲取地圖結果,但在不同(更高)的datact計數處交換地圖結果。仍然很低(在
datact
== 16-35 千之間)。 - 幾乎準確地重寫了這段代碼,但隨機生成的16個字符的序列完美地工作,據我所知(沒有 數據段的段錯誤高達200,000,沒有測試更高)。
- 在(4)中的代碼中,似乎在10000左右有一個rehash,這可能是相關或巧合的。
如果需要,我可以發佈讀取的數據文件。
編輯:解決 代替unordered_map <string,unsigned int*> location
,與unordered_map <string,unsigned int> location
代替(VALUE_TYPE爲int代替INT *)。現在value_type持有ctarr []中的索引。運行良好。謝謝!
有趣的是,我提出了指針的想法,因爲我認爲這會提高內存效率,最終導致頭痛。我沒有注意到這一點的一個原因是因爲它發生在10736年。如果它發生在10001年,我會立即查看矢量調整大小的情況。此外,它不應該嘗試添加到位置,除非該key_value是新的。我期望的錯誤是,程序運行良好,直到試圖迭代指針的目標,當指針不再指向實際值('* location [sequence] + = sct;')時 – vector07
@ vector07 In一般來說,存儲指針可能很容易*少*存儲效率。在具有gcc的x86_64系統上,一個'unsigned int'(用於存儲值或索引)需要4個字節,而一個指針需要8個字節! – us2012