std::无序的_映射在插入特定密钥时引发seg错误 我有一个Python代码库,有时调用C++程序来处理密集的工作负载。其中一个这样的代码必须计算大型文本文件中特定大小的所有kmer。对于它读取的每一行,它都会创建一个临时索引来存储每个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 }

std::无序的_映射在插入特定密钥时引发seg错误 我有一个Python代码库,有时调用C++程序来处理密集的工作负载。其中一个这样的代码必须计算大型文本文件中特定大小的所有kmer。对于它读取的每一行,它都会创建一个临时索引来存储每个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 },c++,unordered-map,C++,Unordered Map,在该行的Kmer中,只有aaaaaaaaaaaaa c和caaaaaaaaa进入索引。由于我不明白的原因,在尝试插入caaaaaaaaaaa时,代码总是崩溃。我想这些键按顺序插入到无序的映射中是有问题的。将此功能更改为此,在插入第二个键时仍会导致相同的崩溃: void process_read(char* read, int num) { std::unordered_map<std::string, std::vector<int>> index ; i

在该行的Kmer中,只有
aaaaaaaaaaaaa c
caaaaaaaaa
进入索引。由于我不明白的原因,在尝试插入
caaaaaaaaaaa
时,代码总是崩溃。我想这些键按顺序插入到无序的映射中是有问题的。将此功能更改为此,在插入第二个键时仍会导致相同的崩溃:

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))) ;
}

函数签名表明您不一定有以null结尾的字符串(最后一个字符是\0)

但您并没有这样对待它(您应该使用以num为参数的变量)。我怀疑这种模式会在其他地方重复,并且在某个时候会破坏你的记忆

如果我是你,我会用Valgrind或其他内存分析工具构建二进制文件,然后再次运行它。它将捕获发生错误的访问

我觉得你使用无序地图的方式很好

将此功能更改为此,在插入第二个键时仍会导致相同的崩溃:

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))) ;
}
[……]

把这段代码放在程序的开头,或者编写另一个只执行这项操作的小程序,似乎并没有重现崩溃,所以我真的很困惑


std::unordered_map
没有相关的全局状态,该状态可能在“如果我在开始时运行此测试函数,一切正常”和“如果我稍后运行此测试函数,则映射崩溃”之间发生变化。由于程序中其他地方的未定义行为,您的内存已损坏-您所做的观察是对此的最有力的证明。

“因此问题必须与这些特定键有关”不是真的-如果您正在损坏内存,崩溃可能出现在意外的地方。您的
std::unordered_map
不太可能对某些键有bug。请使用调试器或内存检查器查看哪里出了问题。@Acorn您是在建议上面未包含的程序中的其他内容正在破坏内存?您可以永远推测,也可以在调试器中一步一步地执行代码,这听起来像是过早的优化。不管怎么说,如果没有一个好朋友,不管怎么说,帮助你都会很困难。还可以考虑使用内存调试器工具,如或类似的。如前面所强调的,这看起来像内存损坏。尝试从只调用process\u read的main运行简单版本。它不会崩溃,但我正在将其转换为字符串并使用它。甚至那个字符串也是只读的。子字符串是从中复制的新字符串。还请注意,这里的两个键的长度都是15,这是预期的值,for循环的边界检查确保我们不会超出字符串。@DarthPaghius请停止尝试解释您认为的(或不是)问题;听3个人给你的建议。@DarthPaghius如果你的输入字符串不是以null结尾的,那么你就不能正确或安全地将其转换为字符串。是这样吗?您的输入是否以null结尾?@darthpaghius这是内存损坏的问题,它不会在您出错的地方崩溃。它可以正常运行一段时间,然后崩溃看起来像是无辜的代码。这就是为什么我建议使用Valgrind,因为它捕捉到了原始错误。字符串处理只是基于我看到的代码的一种怀疑。最初的错误可能有很多种(一个错误导致的错误、索引错误指针或任何其他损坏内存的方法)。@Sorin我无法访问开发系统上的内存调试器,因此我还无法检查。但这将是我第一次尝试,当我可以得到我的手调试器。
*** 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]