我有一个 python 代码库,有时会调用 C++ 程序来处理密集型工作负载。这样的代码必须计算大型文本文件中特定大小的所有公里数。对于它读取的每一行,它都会创建一个临时索引来存储每个 kmer 的位置。这是处理每一行的函数:
void process_read(char* read, int num) {
int l = strlen(read) ;
std::string seq(read) ;
// index kmers
std::unordered_map<std::string, std::vector<int>> index ;
for (int i = 0 ; i <= l - 1 - 15 ; i++) {
std::string k = seq.substr(i, 15) ;
if (global_index->find(k) == global_index->end()) {
continue ;
}
if (index.find(k) == index.end()) {
index.insert(std::make_pair(k, std::vector<int>(1, i))) ;
} else {
index[k].push_back(i) ;
}
}
// 50+ lines of code commented out. It returns here
}
每次到达特定的输入行时,代码都会崩溃:
ACCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCCAAACCATAACCCTAAACCTCACGATAACCCAAACCATCACCAAAAAAAAAAAAAACACACCTACCGAAACCAACAACATA
在该行的 kmers 中,只有 AAAAAAAAAAAAAAC
和 CAAAAAAAAAAAAA
进入索引。由于某种我不明白的原因,尝试插入 CAAAAAAAAAAAAAAA
时,代码总是崩溃。我猜想这些键按顺序插入到 unordered_map
中存在问题。将函数更改为此在插入第二个键时仍然会导致相同的崩溃:
void process_read(char* read, int num) {
std::unordered_map<std::string, std::vector<int>> index ;
index.insert(std::make_pair("AAAAAAAAAAAAAAC", std::vector<int>(1, 2))) ;
index.insert(std::make_pair("CAAAAAAAAAAAAAA", std::vector<int>(1, 2))) ;
}
现在,与原始函数不同,这个函数显然没有访问任何全局状态,因此问题必须出在这些特定键上(请注意,一个是另一个的循环移位,所使用的哈希函数可能对此感到不舒服) ;但是,将此代码放在程序的开头或编写另一个仅执行此操作的小程序似乎不会重现崩溃,所以我真的很困惑。
如有任何建议,我们将不胜感激。
更新: 我在崩溃期间得到了这个堆栈跟踪。由于某些原因,我无法使用 gdb 进行调试,所以我想这是我能得到的最好的结果。但不知道如何解释。
*** Error in `src/python/kmer/c_counter.out': malloc(): memory corruption (fast): 0x0000000001eac690 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x777e5)[0x7f189daa47e5]
/lib/x86_64-linux-gnu/libc.so.6(+0x82651)[0x7f189daaf651]
/lib/x86_64-linux-gnu/libc.so.6(__libc_malloc+0x54)[0x7f189dab1184]
/usr/lib/x86_64-linux-gnu/libstdc++.so.6(_Znwm+0x18)[0x7f189e3a3e78]
/src/python/kmer/c_counter.out[0x41c5e4]
/src/python/kmer/c_counter.out[0x4146ea]
/src/python/kmer/c_counter.out[0x41453a]
/src/python/kmer/c_counter.out[0x41035b]
/src/python/kmer/c_counter.out[0x40b3d8]
/src/python/kmer/c_counter.out[0x40940a]
/src/python/kmer/c_counter.out[0x404528]
/src/python/kmer/c_counter.out[0x404f9d]
/src/python/kmer/c_counter.out[0x405f42]
/src/python/kmer/c_counter.out[0x4063d6]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7f189da4d830]
/src/python/kmer/c_counter.out[0x403b39]
======= Memory map: ========
00400000-00440000 r-xp 00000000 00:2f 546796 src/python/kmer/c_counter.out
0063f000-00640000 rw-p 0003f000 00:2f 546796 src/python/kmer/c_counter.out
014a0000-01ebf000 rw-p 00000000 00:00 0 [heap]
7f1898000000-7f1898021000 rw-p 00000000 00:00 0
7f1898021000-7f189c000000 ---p 00000000 00:00 0
7f189da2d000-7f189dbed000 r-xp 00000000 fc:00 1439150 /lib/x86_64-linux-gnu/libc-2.23.so
7f189dbed000-7f189dded000 ---p 001c0000 fc:00 1439150 /lib/x86_64-linux-gnu/libc-2.23.so
7f189dded000-7f189ddf1000 r--p 001c0000 fc:00 1439150 /lib/x86_64-linux-gnu/libc-2.23.so
7f189ddf1000-7f189ddf3000 rw-p 001c4000 fc:00 1439150 /lib/x86_64-linux-gnu/libc-2.23.so
7f189ddf3000-7f189ddf7000 rw-p 00000000 00:00 0
7f189ddf7000-7f189de0d000 r-xp 00000000 fc:00 1439041 /lib/x86_64-linux-gnu/libgcc_s.so.1
7f189de0d000-7f189e00c000 ---p 00016000 fc:00 1439041 /lib/x86_64-linux-gnu/libgcc_s.so.1
7f189e00c000-7f189e00d000 rw-p 00015000 fc:00 1439041 /lib/x86_64-linux-gnu/libgcc_s.so.1
7f189e00d000-7f189e115000 r-xp 00000000 fc:00 1439141 /lib/x86_64-linux-gnu/libm-2.23.so
7f189e115000-7f189e314000 ---p 00108000 fc:00 1439141 /lib/x86_64-linux-gnu/libm-2.23.so
7f189e314000-7f189e315000 r--p 00107000 fc:00 1439141 /lib/x86_64-linux-gnu/libm-2.23.so
7f189e315000-7f189e316000 rw-p 00108000 fc:00 1439141 /lib/x86_64-linux-gnu/libm-2.23.so
7f189e316000-7f189e488000 r-xp 00000000 fc:00 671990 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21
7f189e488000-7f189e688000 ---p 00172000 fc:00 671990 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21
7f189e688000-7f189e692000 r--p 00172000 fc:00 671990 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21
7f189e692000-7f189e694000 rw-p 0017c000 fc:00 671990 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21
7f189e694000-7f189e698000 rw-p 00000000 00:00 0
7f189e698000-7f189e6be000 r-xp 00000000 fc:00 1439146 /lib/x86_64-linux-gnu/ld-2.23.so
7f189e878000-7f189e89f000 rw-p 00000000 00:00 0
7f189e8bc000-7f189e8bd000 rw-p 00000000 00:00 0
7f189e8bd000-7f189e8be000 r--p 00025000 fc:00 1439146 /lib/x86_64-linux-gnu/ld-2.23.so
7f189e8be000-7f189e8bf000 rw-p 00026000 fc:00 1439146 /lib/x86_64-linux-gnu/ld-2.23.so
7f189e8bf000-7f189e8c0000 rw-p 00000000 00:00 0
7ffea4907000-7ffea4929000 rw-p 00000000 00:00 0 [stack]
7ffea49b6000-7ffea49b9000 r--p 00000000 00:00 0 [vvar]
7ffea49b9000-7ffea49bb000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
最佳答案
Changing the function to this will still result in the same crash when inserting the second key:
[...]
putting this code at the start of the program or writing another small program that only does this doesn't seem to reproduce the crash so I'm really confused.
std::unordered_map
没有相关的全局状态,可以在“如果我在开始时运行此测试函数,一切都很好”和“如果我稍后运行此测试函数, map 崩溃”之间发生变化”。由于程序中其他地方的未定义行为,您出现了内存损坏 - 您所做的观察是您可以获得的最有力的证据。
关于c++ - std::unordered_map 插入特定键时抛出 seg 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52962797/