std::sort中的SIGSEGV,如何缩小它的范围

SIGSEGV within std::sort, how to narrow it down

本文关键字:缩小 范围 何缩小 中的 sort SIGSEGV std      更新时间:2023-10-16

这是一篇与这篇文章相关的文章,因为它处理的是同一个程序,但我现在实现了它的迭代,不再递归,但在运行程序时我仍然得到了SIGSEGV(但稍后(。我对我的程序做了一些其他的更改来缩小它的范围,我认为将对象的向量更改为堆上对象的ptr向量确实会给我一些额外的循环(大约200(,但仍然会崩溃。我建议我在程序中保存变量的内存会耗尽,但当我转储程序的堆栈大小时:

rlimit rlim;
getrlimit(RLIMIT_STACK,&rlim);
std::cout << "rlim_cur ist:" << rlim.rlim_cur << std::endl;
std::cout << "rlim_max ist:" << rlim.rlim_max << std::endl;

输出为:

rlim_cur ist:8388608
rlim_max ist:18446744073709551615

这似乎相当大,而且还没有用完,还有其他相关的限制吗以进一步缩小我的问题范围并希望解决它?

这里是我的调试器的转储:

Program received signal SIGSEGV, Segmentation fault.
0x000000000040b2a0 in Town::get_cur_capacity (this=0x0) at ./solver/Darstellung.cpp:98
98      return left_over_capacity;
(gdb) backtrace
#0  0x000000000040b2a0 in Town::get_cur_capacity (this=0x0) at ./solver/Darstellung.cpp:98
#1  0x000000000040b9ab in Town::compare_by_capacity (eins=0x0, zwei=0x0) at ./solver/Darstellung.cpp:135
#2  0x00000000004124c7 in std::__move_median_first<__gnu_cxx::__normal_iterator<Town**, std::vector<Town*> >, bool (*)(Town const*, Town const*)> (__a=..., __b=..., __c=..., 
    __comp=0x40b98e <Town::compare_by_capacity(Town const*, Town const*)>) at /usr/include/c++/4.5/bits/stl_algo.h:108
#3  0x0000000000411250 in std::__unguarded_partition_pivot<__gnu_cxx::__normal_iterator<Town**, std::vector<Town*> >, bool (*)(Town const*, Town const*)> (__first=..., __last=..., 
    __comp=0x40b98e <Town::compare_by_capacity(Town const*, Town const*)>) at /usr/include/c++/4.5/bits/stl_algo.h:2260
#4  0x000000000040f111 in std::__introsort_loop<__gnu_cxx::__normal_iterator<Town**, std::vector<Town*> >, long, bool (*)(Town const*, Town const*)> (__first=..., __last=..., __depth_limit=21, 
    __comp=0x40b98e <Town::compare_by_capacity(Town const*, Town const*)>) at /usr/include/c++/4.5/bits/stl_algo.h:2302
#5  0x000000000040de63 in std::sort<__gnu_cxx::__normal_iterator<Town**, std::vector<Town*> >, bool (*)(Town const*, Town const*)> (__first=..., __last=..., __comp=0x40b98e <Town::compare_by_capacity(Town const*, Town const*)>)
    at /usr/include/c++/4.5/bits/stl_algo.h:5250
#6  0x000000000040ce5a in Solution_Stack::get_towns_by_capacity (this=0x7fffffffe010) at ./solver/Darstellung.cpp:331
#7  0x000000000040a6cf in solver::treat_towns_with_zero_capacity (ptr=0x7fffffffe010) at ./solver/Solver.cpp:184
#8  0x0000000000409ff2 in solver::solve_problem (ptr=0x7fffffffe010) at ./solver/Solver.cpp:94
#9  0x000000000041475f in main (argc=3, argv=0x7fffffffe208) at ./main/Main.cpp:50

添加检查功能以追踪零值后的新转储:

    #0  0x000000000040b2a0 in Town::get_cur_capacity (this=0x40) at ./solver/Darstellung.cpp:98
    #1  0x000000000040b9e9 in Town::compare_by_index (eins=0x40, zwei=0x73b4d0) at ./solver/Darstellung.cpp:139
    #2  0x000000000040bad1 in Town::compare_by_index_inv (eins=0x40, zwei=0x73b4d0) at ./solver/Darstellung.cpp:153
    #3  0x00000000004127ea in std::__unguarded_partition<__gnu_cxx::__normal_iterator<Town**, std::vector<Town*> >, Town*, bool (*)(Town const*, Town const*)> (
        __first=..., __last=..., __pivot=@0x631ef0, __comp=0x40baae <Town::compare_by_index_inv(Town const*, Town const*)>)
        at /usr/include/c++/4.5/bits/stl_algo.h:2229
    #4  0x0000000000411444 in std::__unguarded_partition_pivot<__gnu_cxx::__normal_iterator<Town**, std::vector<Town*> >, bool (*)(Town const*, Town const*)> (
        __first=..., __last=..., __comp=0x40baae <Town::compare_by_index_inv(Town const*, Town const*)>) at /usr/include/c++/4.5/bits/stl_algo.h:2261
    #5  0x000000000040f2c5 in std::__introsort_loop<__gnu_cxx::__normal_iterator<Town**, std::vector<Town*> >, long, bool (*)(Town const*, Town const*)> (
        __first=..., __last=..., __depth_limit=7, __comp=0x40baae <Town::compare_by_index_inv(Town const*, Town const*)>)
        at /usr/include/c++/4.5/bits/stl_algo.h:2302
    #6  0x000000000040e017 in std::sort<__gnu_cxx::__normal_iterator<Town**, std::vector<Town*> >, bool (*)(Town const*, Town const*)> (__first=..., __last=..., 
        __comp=0x40baae <Town::compare_by_index_inv(Town const*, Town const*)>) at /usr/include/c++/4.5/bits/stl_algo.h:5250
    #7  0x000000000040d1e6 in Solution_Stack::get_partners_of_by_index_inv (this=0x7fffffffe010, id=523) at ./solver/Darstellung.cpp:371
    #8  0x000000000040a4d7 in solver::treat_towns_considering_their_index (ptr=0x7fffffffe010) at ./solver/Solver.cpp:165
    #9  0x000000000040a016 in solver::solve_problem (ptr=0x7fffffffe010) at ./solver/Solver.cpp:100
    #10 0x0000000000414913 in main (argc=3, argv=0x7fffffffe208) at ./main/Main.cpp:50

Valgrind给了我一个垃圾场,就在这个问题过去经常发生的地方。我很困惑,因为它的大小:

==16150== Invalid read of size 4
==16150==    at 0x40B2A0: Town::get_cur_capacity() const (Darstellung.cpp:98)
==16150==    by 0x40B9AA: Town::compare_by_capacity(Town const*, Town const*) (Darstellung.cpp:135)
==16150==    by 0x4124C6: void std::__move_median_first<__gnu_cxx::__normal_iterator<Town**, std::vector<Town*, std::allocator<Town*> > >, bool (*)(Town const*, Town const*)>(__gnu_cxx::__normal_iterator<Town**, std::vector<Town*, std::allocator<Town*> > >, __gnu_cxx::__normal_iterator<Town**, std::vector<Town*, std::allocator<Town*> > >, __gnu_cxx::__normal_iterator<Town**, std::vector<Town*, std::allocator<Town*> > >, bool (*)(Town const*, Town const*)) (stl_algo.h:108)
==16150==    by 0x41124F: __gnu_cxx::__normal_iterator<Town**, std::vector<Town*, std::allocator<Town*> > > std::__unguarded_partition_pivot<__gnu_cxx::__normal_iterator<Town**, std::vector<Town*, std::allocator<Town*> > >, bool (*)(Town const*, Town const*)>(__gnu_cxx::__normal_iterator<Town**, std::vector<Town*, std::allocator<Town*> > >, __gnu_cxx::__normal_iterator<Town**, std::vector<Town*, std::allocator<Town*> > >, bool (*)(Town const*, Town const*)) (stl_algo.h:2260)
==16150==    by 0x40F110: void std::__introsort_loop<__gnu_cxx::__normal_iterator<Town**, std::vector<Town*, std::allocator<Town*> > >, long, bool (*)(Town const*, Town const*)>(__gnu_cxx::__normal_iterator<Town**, std::vector<Town*, std::allocator<Town*> > >, __gnu_cxx::__normal_iterator<Town**, std::vector<Town*, std::allocator<Town*> > >, long, bool (*)(Town const*, Town const*)) (stl_algo.h:2302)
==16150==    by 0x40DE62: void std::sort<__gnu_cxx::__normal_iterator<Town**, std::vector<Town*, std::allocator<Town*> > >, bool (*)(Town const*, Town const*)>(__gnu_cxx::__normal_iterator<Town**, std::vector<Town*, std::allocator<Town*> > >, __gnu_cxx::__normal_iterator<Town**, std::vector<Town*, std::allocator<Town*> > >, bool (*)(Town const*, Town const*)) (stl_algo.h:5250)
==16150==    by 0x40CE59: Solution_Stack::get_towns_by_capacity() (Darstellung.cpp:331)
==16150==    by 0x40A6CE: solver::treat_towns_with_zero_capacity(Solution_Stack*) (Solver.cpp:184)
==16150==    by 0x409FF1: solver::solve_problem(Solution_Stack*) (Solver.cpp:94)
==16150==    by 0x41475E: main (Main.cpp:50)
==16150==  Address 0x8 is not stack'd, malloc'd or (recently) free'd
==16150== 
==16150== 
==16150== Process terminating with default action of signal 11 (SIGSEGV)
==16150==  Access not within mapped region at address 0x8
==16150==    at 0x40B2A0: Town::get_cur_capacity() const (Darstellung.cpp:98)
==16150==    by 0x40B9AA: Town::compare_by_capacity(Town const*, Town const*) (Darstellung.cpp:135)
==16150==    by 0x4124C6: void std::__move_median_first<__gnu_cxx::__normal_iterator<Town**, std::vector<Town*, std::allocator<Town*> > >, bool (*)(Town const*, Town const*)>(__gnu_cxx::__normal_iterator<Town**, std::vector<Town*, std::allocator<Town*> > >, __gnu_cxx::__normal_iterator<Town**, std::vector<Town*, std::allocator<Town*> > >, __gnu_cxx::__normal_iterator<Town**, std::vector<Town*, std::allocator<Town*> > >, bool (*)(Town const*, Town const*)) (stl_algo.h:108)
==16150==    by 0x41124F: __gnu_cxx::__normal_iterator<Town**, std::vector<Town*, std::allocator<Town*> > > std::__unguarded_partition_pivot<__gnu_cxx::__normal_iterator<Town**, std::vector<Town*, std::allocator<Town*> > >, bool (*)(Town const*, Town const*)>(__gnu_cxx::__normal_iterator<Town**, std::vector<Town*, std::allocator<Town*> > >, __gnu_cxx::__normal_iterator<Town**, std::vector<Town*, std::allocator<Town*> > >, bool (*)(Town const*, Town const*)) (stl_algo.h:2260)
==16150==    by 0x40F110: void std::__introsort_loop<__gnu_cxx::__normal_iterator<Town**, std::vector<Town*, std::allocator<Town*> > >, long, bool (*)(Town const*, Town const*)>(__gnu_cxx::__normal_iterator<Town**, std::vector<Town*, std::allocator<Town*> > >, __gnu_cxx::__normal_iterator<Town**, std::vector<Town*, std::allocator<Town*> > >, long, bool (*)(Town const*, Town const*)) (stl_algo.h:2302)
==16150==    by 0x40DE62: void std::sort<__gnu_cxx::__normal_iterator<Town**, std::vector<Town*, std::allocator<Town*> > >, bool (*)(Town const*, Town const*)>(__gnu_cxx::__normal_iterator<Town**, std::vector<Town*, std::allocator<Town*> > >, __gnu_cxx::__normal_iterator<Town**, std::vector<Town*, std::allocator<Town*> > >, bool (*)(Town const*, Town const*)) (stl_algo.h:5250)
==16150==    by 0x40CE59: Solution_Stack::get_towns_by_capacity() (Darstellung.cpp:331)
==16150==    by 0x40A6CE: solver::treat_towns_with_zero_capacity(Solution_Stack*) (Solver.cpp:184)
==16150==    by 0x409FF1: solver::solve_problem(Solution_Stack*) (Solver.cpp:94)
==16150==    by 0x41475E: main (Main.cpp:50)
==16150==  If you believe this happened as a result of a stack
==16150==  overflow in your program's main thread (unlikely but
==16150==  possible), you can try to increase the size of the
==16150==  main thread stack using the --main-stacksize= flag.
==16150==  The main thread stack size used in this run was 8388608.
==16150== 
==16150== HEAP SUMMARY:
==16150==     in use at exit: 771,174 bytes in 19,239 blocks
==16150==   total heap usage: 9,821,251 allocs, 9,802,012 frees, 384,861,557 bytes allocated
==16150== 
==16150== 50,678 bytes in 1,491 blocks are possibly lost in loss record 28 of 35
==16150==    at 0x4C28B42: operator new(unsigned long) (vg_replace_malloc.c:261)
==16150==    by 0x4ECBE6C: std::string::_Rep::_S_create(unsigned long, unsigned long, std::allocator<char> const&) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.14)
==16150==    by 0x4ECC08D: std::string::_M_mutate(unsigned long, unsigned long, unsigned long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.14)
==16150==    by 0x4ECC730: std::string::erase(unsigned long, unsigned long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.14)
==16150==    by 0x407FB6: utility::split_helper(std::string, std::string) (Tools.cpp:28)
==16150==    by 0x4080B5: utility::split_helper(std::string, std::string) (Tools.cpp:49)
==16150==    by 0x4081C3: utility::split(std::string, std::string) (Tools.cpp:66)
==16150==    by 0x40539C: parser::get_city_prototypes(std::vector<std::string, std::allocator<std::string> >) (Parser.cpp:27)
==16150==    by 0x4050EB: parser::get_problem_configuration(std::string, std::string) (Parser.cpp:17)
==16150==    by 0x414699: main (Main.cpp:34)
==16150== 
==16150== 62,606 (11,928 direct, 50,678 indirect) bytes in 1,491 blocks are definitely lost in loss record 30 of 35
==16150==    at 0x4C28B42: operator new(unsigned long) (vg_replace_malloc.c:261)
==16150==    by 0x407F68: utility::split_helper(std::string, std::string) (Tools.cpp:24)
==16150==    by 0x4080B5: utility::split_helper(std::string, std::string) (Tools.cpp:49)
==16150==    by 0x4081C3: utility::split(std::string, std::string) (Tools.cpp:66)
==16150==    by 0x40539C: parser::get_city_prototypes(std::vector<std::string, std::allocator<std::string> >) (Parser.cpp:27)
==16150==    by 0x4050EB: parser::get_problem_configuration(std::string, std::string) (Parser.cpp:17)
==16150==    by 0x414699: main (Main.cpp:34)
==16150== 
==16150== 94,406 (18,440 direct, 75,966 indirect) bytes in 2,305 blocks are definitely lost in loss record 32 of 35
==16150==    at 0x4C28B42: operator new(unsigned long) (vg_replace_malloc.c:261)
==16150==    by 0x407F68: utility::split_helper(std::string, std::string) (Tools.cpp:24)
==16150==    by 0x4080B5: utility::split_helper(std::string, std::string) (Tools.cpp:49)
==16150==    by 0x4081C3: utility::split(std::string, std::string) (Tools.cpp:66)
==16150==    by 0x40573F: parser::get_finished_cities(std::vector<std::string, std::allocator<std::string> >, std::vector<City*, std::allocator<City*> >) (Parser.cpp:42)
==16150==    by 0x40511A: parser::get_problem_configuration(std::string, std::string) (Parser.cpp:17)
==16150==    by 0x414699: main (Main.cpp:34)
==16150== 
==16150== 178,720 (131,208 direct, 47,512 indirect) bytes in 1,491 blocks are definitely lost in loss record 35 of 35
==16150==    at 0x4C28B42: operator new(unsigned long) (vg_replace_malloc.c:261)
==16150==    by 0x40541B: parser::get_city_prototypes(std::vector<std::string, std::allocator<std::string> >) (Parser.cpp:28)
==16150==    by 0x4050EB: parser::get_problem_configuration(std::string, std::string) (Parser.cpp:17)
==16150==    by 0x414699: main (Main.cpp:34)
==16150== 
==16150== LEAK SUMMARY:
==16150==    definitely lost: 161,576 bytes in 5,287 blocks
==16150==    indirectly lost: 174,156 bytes in 5,287 blocks
==16150==      possibly lost: 50,678 bytes in 1,491 blocks
==16150==    still reachable: 384,764 bytes in 7,174 blocks
==16150==         suppressed: 0 bytes in 0 blocks
==16150== Reachable blocks (those to which a pointer was found) are not shown.
==16150== To see them, rerun with: --leak-check=full --show-reachable=yes
==16150== 
==16150== For counts of detected and suppressed errors, rerun with: -v
==16150== Use --track-origins=yes to see where uninitialised values come from
==16150== ERROR SUMMARY: 7 errors from 7 contexts (suppressed: 4 from 4)
#0  0x000000000040b2a0 in Town::get_cur_capacity (this=0x0) at ./solver/Darstellung.cpp:98

看起来您正在对NULL指针调用get_cur_capacity。你是从一个比较器得到的:

#1  0x000000000040b9ab in Town::compare_by_capacity (eins=0x0, zwei=0x0) at ./solver/Darstellung.cpp:135

其将NULL与NULL进行比较。您可以从sort:进一步了解

#5  0x000000000040de63 in std::sort<__gnu_cxx::__normal_iterator<Town**, std::vector<Town*> >, bool (*)(Town const*, Town const*)> (__first=..., __last=..., __comp=0x40b98e <Town::compare_by_capacity(Town const*, Town const*)>)
    at /usr/include/c++/4.5/bits/stl_algo.h:5250

这是对std::vector<Town*>进行排序,调用自:

#6  0x000000000040ce5a in Solution_Stack::get_towns_by_capacity (this=0x7fffffffe010) at ./solver/Darstellung.cpp:331

很可能您正在排序的向量包含NULL指针,而您的compare_by_capacity函数没有准备好处理这种可能性。要么确保向量没有NULL,要么让compare_by_capacity显式检查NULL并做一些合理的事情(例如,在其他NULL之前对其进行排序(。

#1  0x000000000040b9e9 in Town::compare_by_index (eins=0x40, zwei=0x73b4d0) at ./solver/Darstellung.cpp:139

0x40看起来内存未初始化或已损坏。如何调整此矢量的大小?

在没有看到任何代码的情况下尝试诊断这一点真的很困难。

如果您的代码是用调试符号编译的,而没有进行优化,那么我们可能会相信Town::get_cur_capacity (this=0x0)行,这意味着您的向量中有一个空指针。放入它的代码可能在完全不同的时间点运行。

如果向量中实际上允许null,那么排序谓词compare_by_capacity需要准备好处理这种可能性。

在这种情况下,您可能需要查看填充向量的代码,valgrind可能会帮助您跟踪代码中是否存在内存问题。