gpt4 book ai didi

c++ - 删除以结构为键的 map 时出现段错误

转载 作者:塔克拉玛干 更新时间:2023-11-03 06:56:10 25 4
gpt4 key购买 nike

在我的代码中,我有一个用作映射键的结构:

struct index{
int x;
int y;
int z;
bool operator<(const index &b){
bool out = true;
if ( x == b.x ){
if ( y == b.y ){
out = z < b.z;
} else out = y < b.y;
} else out = x < b.x;
return out;
}
};

我使用的 map 是:

map<index,set<std::pair<int, int> > > tBoxes;

当程序结束运行时,我尝试释放内存,当程序尝试删除 map 时,我遇到了段错误。使用 gdb 我得到:

#0  std::_Rb_tree<membrane::index, std::pair<membrane::index const, std::set<std::pair<int, int>, std::less<std::pair<int, int> >, std::allocator<std::pair<int, int> > > >, std::_Select1st<std::pair<membrane::index const, std::set<std::pair<int, int>, std::less<std::pair<int, int> >, std::allocator<std::pair<int, int> > > > >, std::less<membrane::index>, std::allocator<std::pair<membrane::index const, std::set<std::pair<int, int>, std::less<std::pair<int, int> >, std::allocator<std::pair<int, int> > > > > >::_M_erase (this=0x63b900, 
__x=0x404057eb274ede6c)
at /usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_tree.h:1264
#1 0x000000000041ed2f in std::_Rb_tree<membrane::index, std::pair<membrane::index const, std::set<std::pair<int, int>, std::less<std::pair<int, int> >, std::allocator<std::pair<int, int> > > >, std::_Select1st<std::pair<membrane::index const, std::set<std::pair<int, int>, std::less<std::pair<int, int> >, std::allocator<std::pair<int, int> > > > >, std::less<membrane::index>, std::allocator<std::pair<membrane::index const, std::set<std::pair<int, int>, std::less<std::pair<int, int> >, std::allocator<std::pair<int, int> > > > > >::_M_erase (
this=0x63b900, __x=0x7d31110)
at /usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_tree.h:1264
#2 0x000000000041ed2f in std::_Rb_tree<membrane::index, std::pair<membrane::index const, std::set<std::pair<int, int>, std::less<std::pair<int, int> >, std::allocator<std::pair<int, int> > > >, std::_Select1st<std::pair<membrane::index const, std::set<std::pair<int, int>, std::less<std::pair<int, int> >, std::allocator<std::pair<int, int> > > > >, std::less<membrane::index>, std::allocator<std::pair<membrane::index const, std::set<std::pair<int, int>, std::less<std::pair<int, int> >, std::allocator<std::pair<int, int> > > > > >::_M_erase (
this=0x63b900, __x=0x7d30e30)
at /usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_tree.h:1264
#3 0x000000000041ed2f in std::_Rb_tree<membrane::index, std::pair<membrane::index const, std::set<std::pair<int, int>, std::less<std::pair<int, int> >, std::allocator<std::pair<int, int> > > >, std::_Select1st<std::pair<membrane::index const, std::set<std::pair<int, int>, std::less<std::pair<int, int> >, std::allocator<std::pair<int, int> > > > >, std::less<membrane::index>, std::allocator<std::pair<membrane::index const, std::set<std::pair<int, int>, std::less<std::pair<int, int> >, std::allocator<std::pair<int, int> > > > > >::_M_erase (
this=0x63b900, __x=0x7d30b50)
at /usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_tree.h:1264
#4 0x000000000041ed2f in std::_Rb_tree<membrane::index, std::pair<membrane::index const, std::set<std::pair<int, int>, std::less<std::pair<int, int> >, std::allocator<std::pair<int, int> > > >, std::_Select1st<std::pair<membrane::index const, std::set<std::pair<int, int>, std::less<std::pair<int, int> >, std::allocator<std::pair<int, int> > > > >, std::less<membrane::index>, std::allocator<std::pair<membrane::index const, std::set<std::pair<int, int>, std::less<std::pair<int, int> >, std::allocator<std::pair<int, int> > > > > >::_M_erase (
this=0x63b900, __x=0x7d272c0)
at /usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_tree.h:1264
#5 0x0000000000418237 in clear (this=0x63b3e0,
__in_chrg=<value optimized out>)
at /usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_tree.h:692
#6 clear (this=0x63b3e0, __in_chrg=<value optimized out>)
at /usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_map.h:501
#7 membrane::~membrane (this=0x63b3e0, __in_chrg=<value optimized out>)
at memMC.cpp:135
#8 0x0000000000421658 in __tcf_5 () at main.cpp:7
#9 0x000000378ea334f5 in exit () from /lib64/libc.so.6
#10 0x000000378ea1d99b in __libc_start_main () from /lib64/libc.so.6
#11 0x0000000000402309 in _start ()

并使用 valgrind(运行 $valgrind -v --track-origins=yes --leak-check=yes --tool=massig --tool=memcheck --read-var-info=yes -- log-file=error.txt ./mem) 我得到:

==2561==     in use at exit: 0 bytes in 0 blocks
==2561== total heap usage: 3,346,323 allocs, 3,346,323 frees, 98,851,279 bytes allocated
==2561==
==2561== All heap blocks were freed -- no leaks are possible
==2561==
==2561== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 4 from 4)
--2561--
--2561-- used_suppression: 4 dl-hack3
==2561==
==2561== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 4 from 4)

这很烦人,因为它什么也没告诉我。

我尝试手动清除 map (同时打印一些可能提供一些线索的输出:

while (tBoxes.size() > 0){
printf ("%i ", (*tBoxes.begin()).first.x);
printf ("%i ", (*tBoxes.begin()).first.y);
printf ("%i\n", (*tBoxes.begin()).first.z);
while ((*tBoxes.begin()).second.size() > 0){
printf ("a\n");
tgBit1 = (*tBoxes.begin()).second.begin();
(*tBoxes.begin()).second.erase(tgBit1);
printf ("b\n");
}
tBoxes.erase(tBoxes.begin());
}
tBoxes.clear();
tNextBoxes.clear();

我能收集到的全部信息是,当我将 x 从 0 递增到 1 时,删除会崩溃,并且它会在我删除集合的内容之后发生。

为什么会发生这种情况,除了使用 clear() 之外,还有其他方法可以清除 map 吗?

编辑:

我发现了错误。我使用的其中一个 vector 设置不正确,实际上大小为 0。但是,我仍然访问了该 vector 中的元素。

vector 是 double 值,我在除以框大小并将结果四舍五入后使用此值来确定要放入一对的 tBox。我假设我在 index 中使用了一个无效值。问题仍然存在,为什么当我试图访问这个元素时程序没有崩溃...?

最佳答案

我的猜测是您的程序中的其他地方发生了某种堆/堆栈损坏,只有当您的映射试图访问错误的指针/迭代器时才会出现。查看最后一个被删除的迭代器 (0x404057eb274ede6c),与之前的迭代器值 (0x7d31110) 相比,它看起来很可疑。

至于为什么 Valgrind 没有检测到这种损坏?我不是很熟悉这个工具,但是 this question on SE 指出了另一个案例,其中 Valgrind 未能检测到“明显的”不良行为,并且还提出了其他方法来帮助检测它。

我会尝试将崩溃减少到尽可能少的代码。在另一个项目中创建一个小测试用例,看看是否仍然发生崩溃。在 Debug模式下运行和/或使用额外的内存检查来查看是否可以捕获内存损坏(假设它是什么)。

编辑更新:

假设您使用的是 std::vector::operator[],那么此方法不会进行任何边界检查,并且很乐意让您尝试访问不存在的元素。我相信这被指定为未定义的行为,不幸的是,一个可能的结果是没有任何反应。

如果您希望或需要对它们进行边界检查,请使用 std::vector::at(),参见 this question一些细节。通常,只有当您知道所使用的索引在边界内时才使用 [],例如在迭代循环中或手动检查索引时。

关于c++ - 删除以结构为键的 map 时出现段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9502262/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com