Jump to content
  • Advertisement
Sign in to follow this  
monid233

C++ free(): invalid next size (normal)

This topic is 2754 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello everybody!
I'm using ubuntu 10.10, with g++ 4.4.

When I run my game, I get:


*** glibc detected *** /media/Ubuntu10.10Exten/programming/current-programs/c++/Games/orr/orr/ORR: free(): invalid next size (normal): 0x081af1a8 ***
======= Backtrace: =========
/lib/libc.so.6(+0x6c501)[0x3ee501]
/lib/libc.so.6(+0x6dd70)[0x3efd70]
/lib/libc.so.6(cfree+0x6d)[0x3f2e5d]
/usr/lib/libstdc++.so.6(_ZdlPv+0x21)[0x2ff441]
/media/Ubuntu10.10Exten/programming/current-programs/c++/Games/orr/orr/ORR[0x80578df]
/media/Ubuntu10.10Exten/programming/current-programs/c++/Games/orr/orr/ORR[0x8057405]
/media/Ubuntu10.10Exten/programming/current-programs/c++/Games/orr/orr/ORR[0x8056ab8]
/media/Ubuntu10.10Exten/programming/current-programs/c++/Games/orr/orr/ORR[0x8055b52]
/media/Ubuntu10.10Exten/programming/current-programs/c++/Games/orr/orr/ORR[0x80587a2]
/media/Ubuntu10.10Exten/programming/current-programs/c++/Games/orr/orr/ORR[0x8055b6a]
/media/Ubuntu10.10Exten/programming/current-programs/c++/Games/orr/orr/ORR[0x8055195]
/media/Ubuntu10.10Exten/programming/current-programs/c++/Games/orr/orr/ORR[0x80535d1]
/media/Ubuntu10.10Exten/programming/current-programs/c++/Games/orr/orr/ORR[0x8051c94]
/media/Ubuntu10.10Exten/programming/current-programs/c++/Games/orr/orr/ORR[0x80500f1]
/media/Ubuntu10.10Exten/programming/current-programs/c++/Games/orr/orr/ORR[0x804efca]
/media/Ubuntu10.10Exten/programming/current-programs/c++/Games/orr/orr/ORR[0x804f256]
/media/Ubuntu10.10Exten/programming/current-programs/c++/Games/orr/orr/ORR[0x804c9cd]
/media/Ubuntu10.10Exten/programming/current-programs/c++/Games/orr/orr/ORR[0x80673c9]
/media/Ubuntu10.10Exten/programming/current-programs/c++/Games/orr/orr/ORR[0x806222d]
/media/Ubuntu10.10Exten/programming/current-programs/c++/Games/orr/orr/ORR[0x804a29f]
/lib/libc.so.6(__libc_start_main+0xe7)[0x398ce7]
/media/Ubuntu10.10Exten/programming/current-programs/c++/Games/orr/orr/ORR[0x8049bb1]
======= Memory map: ========
00110000-0012c000 r-xp 00000000 08:06 2274 /lib/ld-2.12.1.so
0012c000-0012d000 r--p 0001b000 08:06 2274 /lib/ld-2.12.1.so
0012d000-0012e000 rw-p 0001c000 08:06 2274 /lib/ld-2.12.1.so
0012e000-0012f000 r-xp 00000000 00:00 0 [vdso]
0012f000-0018f000 r-xp 00000000 08:06 7236 /usr/lib/libSDL-1.2.so.0.11.3
0018f000-00190000 ---p 00060000 08:06 7236 /usr/lib/libSDL-1.2.so.0.11.3
00190000-00191000 r--p 00060000 08:06 7236 /usr/lib/libSDL-1.2.so.0.11.3
00191000-00192000 rw-p 00061000 08:06 7236 /usr/lib/libSDL-1.2.so.0.11.3
00192000-001bc000 rw-p 00000000 00:00 0
001bc000-001c7000 r-xp 00000000 08:06 107 /usr/lib/libSDL_image-1.2.so.0.8.2
001c7000-001c8000 r--p 0000a000 08:06 107 /usr/lib/libSDL_image-1.2.so.0.8.2
001c8000-001c9000 rw-p 0000b000 08:06 107 /usr/lib/libSDL_image-1.2.so.0.8.2
001c9000-001d9000 rw-p 00000000 00:00 0
001d9000-001de000 r-xp 00000000 08:06 5106 /usr/lib/libSDL_ttf-2.0.so.0.6.3
001de000-001df000 r--p 00004000 08:06 5106 /usr/lib/libSDL_ttf-2.0.so.0.6.3
001df000-001e0000 rw-p 00005000 08:06 5106 /usr/lib/libSDL_ttf-2.0.so.0.6.3
001e0000-00207000 r-xp 00000000 08:06 4253 /usr/lib/libSDL_mixer-1.2.so.0.2.6
00207000-00208000 r--p 00026000 08:06 4253 /usr/lib/libSDL_mixer-1.2.so.0.2.6
00208000-00211000 rw-p 00027000 08:06 4253 /usr/lib/libSDL_mixer-1.2.so.0.2.6
00211000-0023b000 rw-p 00000000 00:00 0
0023b000-00250000 r-xp 00000000 08:06 6167 /lib/libpthread-2.12.1.so
00250000-00251000 ---p 00015000 08:06 6167 /lib/libpthread-2.12.1.so
00251000-00252000 r--p 00015000 08:06 6167 /lib/libpthread-2.12.1.so
00252000-00253000 rw-p 00016000 08:06 6167 /lib/libpthread-2.12.1.so
00253000-00255000 rw-p 00000000 00:00 0
00255000-00334000 r-xp 00000000 08:06 863 /usr/lib/libstdc++.so.6.0.14
00334000-00338000 r--p 000de000 08:06 863 /usr/lib/libstdc++.so.6.0.14
00338000-00339000 rw-p 000e2000 08:06 863 /usr/lib/libstdc++.so.6.0.14
00339000-00340000 rw-p 00000000 00:00 0
00340000-00364000 r-xp 00000000 08:06 3643 /lib/libm-2.12.1.so
00364000-00365000 r--p 00023000 08:06 3643 /lib/libm-2.12.1.so
00365000-00366000 rw-p 00024000 08:06 3643 /lib/libm-2.12.1.so
00366000-00380000 r-xp 00000000 08:06 922 /lib/libgcc_s.so.1
00380000-00381000 r--p 00019000 08:06 922 /lib/libgcc_s.so.1
00381000-00382000 rw-p 0001a000 08:06 922 /lib/libgcc_s.so.1
00382000-004d9000 r-xp 00000000 08:06 2935 /lib/libc-2.12.1.so
004d9000-004db000 r--p 00157000 08:06 2935 /lib/libc-2.12.1.so
004db000-004dc000 rw-p 00159000 08:06 2935 /lib/libc-2.12.1.so
004dc000-004df000 rw-p 00000000 00:00 0
004df000-004e1000 r-xp 00000000 08:06 3369 /lib/libdl-2.12.1.so
004e1000-004e2000 r--p 00001000 08:06 3369 /lib/libdl-2.12.1.so
004e2000-004e3000 rw-p 00002000 08:06 3369 /lib/libdl-2.12.1.so
004e3000-004e6000 r-xp 00000000 08:06 4724 /usr/lib/libpulse-simple.so.0.0.3
004e6000-004e7000 r--p 00002000 08:06 4724 /usr/lib/libpulse-simple.so.0.0.3
004e7000-004e8000 rw-p 00003000 08:06 4724 /usr/lib/libpulse-simple.so.0.0.3
004e8000-00527000 r-xp 00000000 08:06 2782 /usr/lib/libpulse.so.0.12.2
00527000-00528000 ---p 0003f000 08:06 2782 /usr/lib/libpulse.so.0.12.2
00528000-00529000 r--p 0003f000 08:06 2782 /usr/lib/libpulse.so.0.12.2
00529000-0052a000 rw-p 00040000 08:06 2782 /usr/lib/libpulse.so.0.12.2
0052a000-00581000 r-xp 00000000 08:06 4868 /usr/lib/libtiff.so.4.3.3
00581000-00582000 ---p 00057000 08:06 4868 /usr/lib/libtiff.so.4.3.3
00582000-00584000 r--p 00057000 08:06 4868 /usr/lib/libtiff.so.4.3.3
00584000-00585000 rw-p 00059000 08:06 4868 /usr/lib/libtiff.so.4.3.3
00585000-005a4000 r-xp 00000000 08:06 4055 /usr/lib/libjpeg.so.62.0.0
005a4000-005a5000 r--p 0001e000 08:06 4055 /usr/lib/libjpeg.so.62.0.0
005a5000-005a6000 rw-p 0001f000 08:06 4055 /usr/lib/libjpeg.so.62.0.0
005a6000-005b9000 r-xp 00000000 08:06 861 /lib/libz.so.1.2.3.4
005b9000-005ba000 r--p 00012000 08:06 861 /lib/libz.so.1.2.3.4
005ba000-005bb000 rw-p 00013000 08:06 861 /lib/libz.so.1.2.3.4
005bb000-0062d000 r-xp 00000000 08:06 916 /usr/lib/libfreetype.so.6.6.0
0062d000-00631000 r--p 00071000 08:06 916 /usr/lib/libfreetype.so.6.6.0
00631000-00632000 rw-p 00075000 08:06 916 /usr/lib/libfreetype.so.6.6.0
00632000-0067b000 r-xp 00000000 08:06 3942 /usr/lib/libmikmod.so.2.0.4
0067b000-0067c000 r--p 00049000 08:06 3942 /usr/lib/libmikmod.so.2.0.4
0067c000-0067d000 rw-p 0004a000 08:06 3942 /usr/lib/libmikmod.so.2.0.4
0067d000-0067e000 rw-p 00000000 00:00 0
0067e000-00685000 r-xp 00000000 08:06 4565 /usr/lib/libvorbisfile.so.3.3.2
00685000-00686000 r--p 00006000 08:06 4565 /usr/lib/libvorbisfile.so.3.3.2
00686000-00687000 rw-p 00007000 08:06 4565 /usr/lib/libvorbisfile.so.3.3.2
00687000-006c2000 r-xp 00000000 08:06 5062 /usr/lib/libsmpeg-0.4.so.0.1.4
006c2000-006c3000 r--p 0003a000 08:06 5062 /usr/lib/libs
Program received signal SIGABRT, Aborted.
0x0012e416 in __kernel_vsyscall ()
(gdb) backtrace
#0 0x0012e416 in __kernel_vsyscall ()
#1 0x003ac941 in raise () from /lib/libc.so.6
#2 0x003afe42 in abort () from /lib/libc.so.6
#3 0x003e4305 in ?? () from /lib/libc.so.6
#4 0x003ee501 in ?? () from /lib/libc.so.6
#5 0x003efd70 in ?? () from /lib/libc.so.6
#6 0x003f2e5d in free () from /lib/libc.so.6
#7 0x002ff441 in operator delete(void*) () from /usr/lib/libstdc++.so.6
#8 0x080578df in __gnu_cxx::new_allocator<tool>::deallocate (this=0x81af0e8,
__p=0x81af1a8) at /usr/include/c++/4.4/ext/new_allocator.h:95
#9 0x08057405 in std::_Vector_base<tool, std::allocator<tool> >::_M_deallocate
(this=0x81af0e8, __p=0x81af1a8, __n=1)
at /usr/include/c++/4.4/bits/stl_vector.h:146
#10 0x08056ab8 in std::_Vector_base<tool, std::allocator<tool> >::~_Vector_base
(this=0x81af0e8, __in_chrg=<value optimized out>)
at /usr/include/c++/4.4/bits/stl_vector.h:132
#11 0x08055b52 in std::vector<tool, std::allocator<tool> >::~vector (
this=0x81af0e8, __in_chrg=<value optimized out>)
at /usr/include/c++/4.4/bits/stl_vector.h:313
#12 0x080587a2 in bClassUnit::~bClassUnit (this=0x81af080,
__in_chrg=<value optimized out>) at EObject.hpp:14
#13 0x08055b6a in std::_Destroy<bClassUnit> (__pointer=0x81af080)
at /usr/include/c++/4.4/bits/stl_construct.h:83
---Type <return> to continue, or q <return> to quit---
#14 0x08055195 in std::_Destroy_aux<false>::__destroy<__gnu_cxx::__normal_iterator<bClassUnit*, std::vector<bClassUnit, std::allocator<bClassUnit> > > > (
__first=..., __last=...) at /usr/include/c++/4.4/bits/stl_construct.h:93
#15 0x080535d1 in std::_Destroy<__gnu_cxx::__normal_iterator<bClassUnit*, std::vector<bClassUnit, std::allocator<bClassUnit> > > > (__first=..., __last=...)
at /usr/include/c++/4.4/bits/stl_construct.h:116
#16 0x08051c94 in std::_Destroy<__gnu_cxx::__normal_iterator<bClassUnit*, std::vector<bClassUnit, std::allocator<bClassUnit> > >, bClassUnit> (__first=...,
__last=...) at /usr/include/c++/4.4/bits/stl_construct.h:142
#17 0x080500f1 in std::vector<bClassUnit, std::allocator<bClassUnit> >::operator= (this=0xbfffecf4, __x=...) at /usr/include/c++/4.4/bits/vector.tcc:176
#18 0x0804efca in tile::operator= (this=0xbfffecd4) at EObject.hpp:258
#19 0x0804f256 in node::operator= (this=0xbfffecc8) at EbClassUnit.cpp:631
#20 0x0804c9cd in bClassUnit::calculate_path (this=0x81af380)
at EbClassUnit.cpp:822
#21 0x080673c9 in tile::update (this=0x82034f0) at terrain.cpp:105
#22 0x0806222d in update () at update.cpp:507
#23 0x0804a29f in main (argc=1, argv=0xbffff3f4) at main.cpp:97



This occurs whenever a unit tries to move somewhere after a wall has been drilled.
Here's the line in my code where it crashes:
n = examineSet.top(); // Get the best next node
That first snippet of code would be from the file, "EbClassUnit.cpp", line 822. Here's the entire file: http://code.google.c...ec=svn234&r=234
The most frustrating part is the crash is jumping around through my code.
At some points, it's when I try to "push_back()" into a vector, or "pop()" from a vector. Although, these crashes, regardless of where in the code they occur, only occur after a wall has been mined...
More info: Here's where nemiver stops tracing the call stack:
// __p is not permitted to be a null pointer.
void
deallocate(pointer __p, size_type)
{ ::operator delete(__p); }

That snippet of code is in new_allocator.h


Here's a link to the google code repo for this game: http://code.google.c...rock-raiders-c/

Yes, I did a lot of debugging, but I just can't seem fix the error!
Many thanks in advance!

Share this post


Link to post
Share on other sites
Advertisement
This doesn't really solve your problem (at least, not in the short term), but a few suggestions:

1. Use constructors (with initializer lists) and destructors instead of init() and destroy() functions (RAII).
2. Does everything in those classes really need to be public? Access control will also help you consider what each class should actually contain.
3. Refactor so that each class does only one thing (the "single responsibility principle").
4. Think about what happens when you copy objects, what you actually want to happen, and hence whether you need to define copy / assignment operators (note the "rule of three").
5. Look into const correctness: member functions that don't alter an object should be const, unchanging class parameters to functions should be const references (e.g. const std::string& foo), not passed by value.
6. Don't use magic numbers (e.g. 32).
(7. Your file organisation is little weird. Try putting just one or two classes per header / .cpp pair, and name the header based on the class, rather than something less descriptive.)

An example:

* Your node class's init function could be a constructor initializer list, so you don't have to remember to call init every time you create a node.
* The calculate cost functions take classes by value, rather than by reference, so the whole thing is being copied every time you pass it in, which is unnecessary.
* getNeighbours() could be a const member function (it doesn't actually alter the node class) (it could even not be a member function and take the node as a const node&).

* Perhaps most important is copying things. Your node class contains a tile directly, not a pointer to a tile or a tile reference. Every time you copy a node (e.g. pushing it onto a vector or calling n= examineSet.top()), you're copying that tile too. Your tile class contains many values, including several vectors. Each of those vectors will be copied -> that means copying every single value in each vector. The tile class also contains an a vector iterator. This will be copied, but still point to the vector in the original class, not to the vector in the new copy. To get around this, you need to not store tile by value, and / or define copy constructors.
[font="Monaco,"] [/font]

Share this post


Link to post
Share on other sites
What you're seeing is a classic symptom of a double deletion. The most probably cause of your problem is a pointer that has been deleted twice, but it's possible it is caused by an array walker or writing to memory of an object that has already been deleted.

The name of the best tool to detect these problems on Linux is 'valgrind'. Compile with "-O0 -ggdb3" and run valgrind until you get no errors, then rerun it with --leak-check=full until you get no errors. Also, enable "-Wall -Wextra -pedantic" on your GCC command line, and fix all of the warnings you see.

As an added tip, read up on C++ idioms and make good use of them. In particular, the widespread use of the RAII idiom and the Rule of Three (google for these) will help prevent this and similar problems at the design stage, where it is cheapest and easiest to fix them.

Share this post


Link to post
Share on other sites

-snipped text-


Thank you very much! I appreciate the advice!



What you're seeing is a classic symptom of a double deletion. The most probably cause of your problem is a pointer that has been deleted twice, but it's possible it is caused by an array walker or writing to memory of an object that has already been deleted.

The name of the best tool to detect these problems on Linux is 'valgrind'. Compile with "-O0 -ggdb3" and run valgrind until you get no errors, then rerun it with --leak-check=full until you get no errors. Also, enable "-Wall -Wextra -pedantic" on your GCC command line, and fix all of the warnings you see.

As an added tip, read up on C++ idioms and make good use of them. In particular, the widespread use of the RAII idiom and the Rule of Three (google for these) will help prevent this and similar problems at the design stage, where it is cheapest and easiest to fix them.


Ok, here's what I did:
I added the flags you specified to the makefile, then recompiled the game.
Afterwards, I typed "valgrind ./ORR" into the terminal. I did everything I could, BUT IT DID NOT CRASH ONCE!
Then, from the terminal, I ran my game directly.
The game crashed in the same places it usually does.
I've rerun valgrind several times already, recompiled the game too, but it runs perfectly in valgrind. Although the errors still exist when I run the game directly. I'm very confused.

Share this post


Link to post
Share on other sites
#0 __kernel_vsyscall() at :0
#1 raise(sig = 6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64
#2 abort() at abort.c:92
#3 __libc_message(do_abort = 2, fmt = 0x4bc280 \"*** glibc detected *** %s: %s: 0x%s ***\\n\") at ../sysdeps/unix/sysv/linux/libc_fatal.c:189
#4 malloc_printerr(action = <value optimized out>, str = 0x6 <Address 0x6 out of bounds>, ptr = 0x82262f8) at malloc.c:6283
#5 _int_free(av = <value optimized out>, p = <value optimized out>) at malloc.c:4795
#6 __libc_free(mem = 0x82262f8) at malloc.c:3738
#7 operator delete(void*)() at :0
#8 __gnu_cxx::new_allocator<tool>::deallocate(this = 0x8226238, __p = 0x82262f8) at /usr/include/c++/4.4/ext/new_allocator.h:95
#9 std::_Vector_base<tool, std::allocator<tool> >::_M_deallocate(this = 0x8226238, __p = 0x82262f8, __n = 1) at /usr/include/c++/4.4/bits/stl_vector.h:146
#10 std::_Vector_base<tool, std::allocator<tool> >::~_Vector_base(this = 0x8226238) at /usr/include/c++/4.4/bits/stl_vector.h:132
#11 std::vector<tool, std::allocator<tool> >::~vector(this = 0x8226238) at /usr/include/c++/4.4/bits/stl_vector.h:313
#12 bClassUnit::~bClassUnit(this = 0x82261d0) at EObject.hpp:14
#13 std::_Destroy<bClassUnit>(__pointer = 0x82261d0) at /usr/include/c++/4.4/bits/stl_construct.h:83
#14 std::_Destroy_aux<false>::__destroy<__gnu_cxx::__normal_iterator<bClassUnit*, std::vector<bClassUnit, std::allocator<bClassUnit> > > >(__first = , __last = ) at /usr/include/c++/4.4/bits/stl_construct.h:93
#15 std::_Destroy<__gnu_cxx::__normal_iterator<bClassUnit*, std::vector<bClassUnit, std::allocator<bClassUnit> > > >(__first = , __last = ) at /usr/include/c++/4.4/bits/stl_construct.h:116
#16 std::_Destroy<__gnu_cxx::__normal_iterator<bClassUnit*, std::vector<bClassUnit, std::allocator<bClassUnit> > >, bClassUnit>(__first = , __last = ) at /usr/include/c++/4.4/bits/stl_construct.h:142
#17 std::vector<bClassUnit, std::allocator<bClassUnit> >::operator=(this = 0xbffff204, __x = ) at /usr/include/c++/4.4/bits/vector.tcc:176
#18 tile::operator=(this = 0xbffff1e4) at EObject.hpp:260
#19 node::operator=(this = 0xbffff1d8) at EbClassUnit.cpp:643
#20 bClassUnit::calculate_path(this = 0x82264e0) at EbClassUnit.cpp:846
#21 tile::update(this = 0x827a648) at terrain.cpp:125
#22 update() at update.cpp:507
#23 main(argc = 1, argv = 0xbffff904) at main.cpp:97

I looked in nemiver, saw that, and took notice of line #9.
It is the last part that has a "std::_Vector_base" thing, and look at the value: tool.
And line #8, "__gnu_cxx::new_allocator<tool>"
I figured that the tool class is causing the program to throw up. So I created a deconstructor for it.
Afterwards, this is what nemiver told me:
#0 __kernel_vsyscall() at :0
#1 raise(sig = 6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64
#2 abort() at abort.c:92
#3 __libc_message(do_abort = 2, fmt = 0x4bc280 \"*** glibc detected *** %s: %s: 0x%s ***\\n\") at ../sysdeps/unix/sysv/linux/libc_fatal.c:189
#4 malloc_printerr(action = <value optimized out>, str = 0x6 <Address 0x6 out of bounds>, ptr = 0x8226400) at malloc.c:6283
#5 _int_free(av = <value optimized out>, p = <value optimized out>) at malloc.c:4795
#6 __libc_free(mem = 0x8226400) at malloc.c:3738
#7 operator delete(void*)() at :0
#8 __gnu_cxx::new_allocator<int>::deallocate(this = 0xbfffedf0, __p = 0x8226400) at /usr/include/c++/4.4/ext/new_allocator.h:95
#9 std::_Vector_base<int, std::allocator<int> >::_M_deallocate(this = 0xbfffedf0, __p = 0x8226400, __n = 2) at /usr/include/c++/4.4/bits/stl_vector.h:146
#10 std::_Vector_base<int, std::allocator<int> >::~_Vector_base(this = 0xbfffedf0) at /usr/include/c++/4.4/bits/stl_vector.h:132
#11 std::vector<int, std::allocator<int> >::~vector(this = 0xbfffedf0) at /usr/include/c++/4.4/bits/stl_vector.h:313
#12 tile::~tile(this = 0xbfffed64) at EObject.hpp:261
#13 node::~node(this = 0xbfffed58) at EbClassUnit.cpp:643
#14 std::push_heap<__gnu_cxx::__normal_iterator<node*, std::vector<node, std::allocator<node> > >, nodeCompare>(__first = , __last = , __comp = ) at /usr/include/c++/4.4/bits/stl_heap.h:218
#15 std::priority_queue<node, std::vector<node, std::allocator<node> >, nodeCompare>::push(this = 0xbffff428, __x = ) at /usr/include/c++/4.4/bits/stl_queue.h:512
#16 bClassUnit::calculate_path(this = 0x82265b0) at EbClassUnit.cpp:841
#17 tile::update(this = 0x827a718) at terrain.cpp:132
#18 update() at update.cpp:507
#19 main(argc = 1, argv = 0xbffff904) at main.cpp:97

So I was like, "Kay, hang on a sec mr computer, I'mma go write a deconstructor for class node."

I did that, recompiled and ran nemiver again.
This time it worked. So I decided to verify that I was done by running the game directly.
It crashed. So I was like, "ARGH. You know what, all of the classes need deconstructors. I'm gonna go write them now."
Did that, but still didn't work again!
#0 __kernel_vsyscall() at :0
#1 raise(sig = 6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64
#2 abort() at abort.c:92
#3 __libc_message(do_abort = 2, fmt = 0x4bc280 \"*** glibc detected *** %s: %s: 0x%s ***\\n\") at ../sysdeps/unix/sysv/linux/libc_fatal.c:189
#4 malloc_printerr(action = <value optimized out>, str = 0x6 <Address 0x6 out of bounds>, ptr = 0x82272e8) at malloc.c:6283
#5 _int_free(av = <value optimized out>, p = <value optimized out>) at malloc.c:4795
#6 __libc_free(mem = 0x82272e8) at malloc.c:3738
#7 operator delete(void*)() at :0
#8 __gnu_cxx::new_allocator<tool>::deallocate(this = 0x82415c0, __p = 0x82272e8) at /usr/include/c++/4.4/ext/new_allocator.h:95
#9 std::_Vector_base<tool, std::allocator<tool> >::_M_deallocate(this = 0x82415c0, __p = 0x82272e8, __n = 1) at /usr/include/c++/4.4/bits/stl_vector.h:146
#10 std::_Vector_base<tool, std::allocator<tool> >::~_Vector_base(this = 0x82415c0) at /usr/include/c++/4.4/bits/stl_vector.h:132
#11 std::vector<tool, std::allocator<tool> >::~vector(this = 0x82415c0) at /usr/include/c++/4.4/bits/stl_vector.h:313
#12 bClassUnit::~bClassUnit(this = 0x8241558) at EObject.hpp:127
#13 std::_Destroy<bClassUnit>(__pointer = 0x8241558) at /usr/include/c++/4.4/bits/stl_construct.h:83
#14 std::_Destroy_aux<false>::__destroy<bClassUnit*>(__first = 0x8241558, __last = 0x824167c) at /usr/include/c++/4.4/bits/stl_construct.h:93
#15 std::_Destroy<bClassUnit*>(__first = 0x8241558, __last = 0x824167c) at /usr/include/c++/4.4/bits/stl_construct.h:116
#16 std::_Destroy<bClassUnit*, bClassUnit>(__first = 0x8241558, __last = 0x824167c) at /usr/include/c++/4.4/bits/stl_construct.h:142
#17 std::vector<bClassUnit, std::allocator<bClassUnit> >::~vector(this = 0xbfffeb74) at /usr/include/c++/4.4/bits/stl_vector.h:313
#18 tile::~tile(this = 0xbfffeb54) at EObject.hpp:315
#19 node::~node(this = 0xbfffeb48) at EbClassUnit.cpp:816
#20 std::__adjust_heap<__gnu_cxx::__normal_iterator<node*, std::vector<node, std::allocator<node> > >, int, node, nodeCompare>(__first = , __holeIndex = 0, __len = 1, __value = , __comp = ) at /usr/include/c++/4.4/bits/stl_heap.h:316
#21 std::__pop_heap<__gnu_cxx::__normal_iterator<node*, std::vector<node, std::allocator<node> > >, nodeCompare>(__first = , __last = , __result = , __comp = ) at /usr/include/c++/4.4/bits/stl_heap.h:332
#22 std::pop_heap<__gnu_cxx::__normal_iterator<node*, std::vector<node, std::allocator<node> > >, nodeCompare>(__first = , __last = , __comp = ) at /usr/include/c++/4.4/bits/stl_heap.h:360
#23 std::priority_queue<node, std::vector<node, std::allocator<node> >, nodeCompare>::pop(this = 0xbffff428) at /usr/include/c++/4.4/bits/stl_queue.h:547
#24 bClassUnit::calculate_path(this = 0x8240c30) at EbClassUnit.cpp:932
#25 tile::update(this = 0x827abb8) at terrain.cpp:125
#26 update() at update.cpp:507
#27 main(argc = 1, argv = 0xbffff904) at main.cpp:97

It's still failing with the tools! Argh!
Oh, at this specific crash, the game crashed on the following line:
examineSet.pop(); // Remove from list to be checked
This is two lines below the earlier error with "n = examineSet.top()"...

Then I decided to write all the constructors too, for the classes. When recompiled and ran, PROGRESS!

node n; // Create a node from the starting tile 'current'
n.init();
n.thisTile = Map[current];
n.calculateCostToTile(Map[destination]); // Destination is stored in 'destination'
n.calculateCosts();

examineSet.push(n); // Add starting node to nodes to be checked
allNodes.push_back(n); // Add this tile to the list of all tiles

while (!examineSet.empty()) // While we have objects to check
{
n = examineSet.top(); // Get the best next node
doneSet.push_back(n); // Add it to the list of good nodes
examineSet.pop(); // Remove from list to be checked

//Stuff...
}

if (goal) // Have we suceeded this run?
{
//More stuff...
}
else
{
//Even more stuff...
}

} //End of scope. node n is destroyed, and this is where the game crashes now.

See? The problem is node n.
Here's the call stack:
#0 __kernel_vsyscall() at :0
#1 raise(sig = 6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64
#2 abort() at abort.c:92
#3 __libc_message(do_abort = 2, fmt = 0x4bc280 \"*** glibc detected *** %s: %s: 0x%s ***\\n\") at ../sysdeps/unix/sysv/linux/libc_fatal.c:189
#4 malloc_printerr(action = <value optimized out>, str = 0x6 <Address 0x6 out of bounds>, ptr = 0x82271e8) at malloc.c:6283
#5 _int_free(av = <value optimized out>, p = <value optimized out>) at malloc.c:4795
#6 __libc_free(mem = 0x82271e8) at malloc.c:3738
#7 operator delete(void*)() at :0
#8 __gnu_cxx::new_allocator<bClassUnit>::deallocate(this = 0xbffff204, __p = 0x82271e8) at /usr/include/c++/4.4/ext/new_allocator.h:95
#9 std::_Vector_base<bClassUnit, std::allocator<bClassUnit> >::_M_deallocate(this = 0xbffff204, __p = 0x82271e8, __n = 1) at /usr/include/c++/4.4/bits/stl_vector.h:146
#10 std::_Vector_base<bClassUnit, std::allocator<bClassUnit> >::~_Vector_base(this = 0xbffff204) at /usr/include/c++/4.4/bits/stl_vector.h:132
#11 std::vector<bClassUnit, std::allocator<bClassUnit> >::~vector(this = 0xbffff204) at /usr/include/c++/4.4/bits/stl_vector.h:313
#12 tile::~tile(this = 0xbffff1e4) at EObject.hpp:315
#13 node::~node(this = 0xbffff1d8) at EbClassUnit.cpp:816
#14 bClassUnit::calculate_path(this = 0x8240be8) at EbClassUnit.cpp:1021
#15 tile::update(this = 0x827ab98) at terrain.cpp:125
#16 update() at update.cpp:507
#17 main(argc = 1, argv = 0xbffff904) at main.cpp:97

I believed it was having problems deallocating the thisTile. So I turned it into a pointer, did all the neccessary changes, and reran.
It worked!

New code, for those that are interested:
[spoiler]//A star pathfinding, wraps a tile
class node;
class node
{
public:
float fCost;
float gCost;
float hCost;
tile* thisTile;
int parent;

void init()
{
}

void calculateGCost(vector<node> lon)
{
if (!(parent == -1))
{
gCost = lon.at(parent).gCost + 10;
}
else
{
gCost = 10;
}
}

void calculateCosts()
{
fCost = gCost + hCost;
}
void calculateCostToNode(const node oNode)
{
hCost = abs(thisTile->wx - oNode.thisTile->wx) + abs(thisTile->wy - oNode.thisTile->wy) * 10.0f;
}
void calculateCostToTile(const tile oTile)
{
hCost = abs(thisTile->wx - oTile.wx) + abs(thisTile->wy - oTile.wy) * 10.0f;
}
int getNeighbors(node *nbors)
{
int i = 0;
tile *t = &Map[((thisTile->wx / 32) + ((thisTile->wy / 32)) + ((num_row_objects - 1)* (thisTile->wy / 32 - 1)) - 1) + (num_col_objects*num_row_objects)*(thisTile->layer)];
if (!t->wall && !t->air)
{
node n;
n.init();
//n.parent = this;
n.thisTile = t; //TODO: Might need to change these to *t;...
nbors = n;
i++;
}
t = &Map[((thisTile->wx / 32) + (thisTile->wy / 32)) + ((num_col_objects - 1)* (thisTile->wy / 32 + 1)) + 1 + (num_col_objects*num_row_objects)*(thisTile->layer)];
if (!t->wall && !t->air)
{
node n;
n.init();
//n.parent = this;
n.thisTile = t;
nbors = n;
i++;
}
t = &Map[((thisTile->wx) / 32) + ((thisTile->wy) / 32) + ((num_row_objects - 1)* ((thisTile->wy / 32))) + 1 + (num_col_objects*num_row_objects)*(thisTile->layer)];
if (!t->wall && !t->air)
{
node n;
n.init();
//n.parent = this;
n.thisTile = t;
nbors = n;
i++;
}
t = &Map[((thisTile->wx) / 32) + ((thisTile->wy) / 32) + ((num_row_objects - 1)* ((thisTile->wy / 32))) - 1 + (num_col_objects*num_row_objects)*(thisTile->layer)];
if (!t->wall && !t->air)
{
node n;
n.init();
//n.parent = this;
n.thisTile = t;
nbors = n;
i++;
}

return i;
}

node() //The constructor. Initialize an empty node.
{
fCost = 0.0f;
gCost = 0.0f;
hCost = 0.0f;
parent = -1;
}
~node() //The deconstructor.
{
}
node(const node &cNode) //The copy constructor.
{
fCost = cNode.fCost;
gCost = cNode.gCost;
hCost = cNode.hCost;
parent = cNode.parent;
thisTile = cNode.thisTile;
}
};
//Compares 2 nodes for best one
class nodeCompare
{
public:
bool operator() (const node& nodeA, const node& nodeB) const
{
return nodeA.fCost > nodeB.fCost;
}
};

bool bClassUnit::calculate_path()
{
if(move == false) //If the unit isn't going anywhere...
{
cout << "Error: Can't calculate a path becuase there is no destination!\n";
out_string << "Error: Can't calculate a path becuase there is no destination!\n";
return false; //Return to the callign function. False lets it know that no path has been found. The above things log why it failed.
}
if(Map[move_destination].wall == true) //If the destination is a wall...
{
cout << "Error: Can't move on a wall!\n";
out_string << "Error: Can't move on a wall!\n";
return false; //Return to the calling function. False lets it know that no path is found. The above things log why it failed.
}
if (Map[move_destination].ramp && Map[move_destination].layer == this->layer)
{
move_destination = (num_col_objects*num_row_objects)*(Map[move_destination].up_ramp ? 1 : -1) + move_destination;
}

vector<node> allNodes;
vector<int> thisMove;

int destination = move_destination;
int start = (((((wx) / 32) + ((wy) / 32)) + ((num_col_objects - 1)* ((wy / 32)) ) )) + (num_col_objects*num_row_objects)*(this->layer);
int current = start;
bool goal = false;
int bestRamp = -1;
int layerChange = 0;

do
{

// Determine if we have to gp up or down or stay
if (Map[destination].layer < Map[current].layer)
layerChange = -1;
else if (Map[destination].layer > Map[current].layer)
layerChange = 1;
else
layerChange = 0;

bestRamp = -1;
// Find the ramp that is closes to 'current'
for (int i = (num_col_objects*num_row_objects)*(Map[current].layer); i < (num_col_objects*num_row_objects)*(abs(layerChange)+Map[current].layer); i++)
{
if (i < 0 || i > Map.size())
{
cout << "Problem at line 657\n";
return false;
}
// Is this a ramp in the right direction?
if (Map.at(i).ramp && ((Map.at(i).down_ramp && layerChange < 0) || (Map.at(i).up_ramp && layerChange > 0)))
{
if (bestRamp == -1)
{
// Make sure that the bestRamp is set
bestRamp = i;
continue;
}
// Calculate the distances to the ramps, from our 'current' position
float newDistance = 10.0f * (abs(Map[current].wx - Map.wx) + abs(Map[current].wy - Map.wy));
float oldDistance = 10.0f * (abs(Map[current].wx - Map[bestRamp].wx) + abs(Map[current].wy - Map[bestRamp].wy));

if (newDistance < oldDistance)
bestRamp = i; // We have found a closer ramp
}
}
if (layerChange == 0)
{
bestRamp = move_destination;
}
if (bestRamp == -1)
{
cout << "Error unable to find suitable ramp on this level\n";
return false;
}
//Now we know which ramp is the closest to 'current'

destination = bestRamp; // We need to get to the 'bestRamp first'

// Try to find a path clear of obstacles to the destination.
priority_queue<node, vector<node>, nodeCompare> examineSet; // Nodes to check
vector<node> doneSet; // Nodes that are complete

node n; // Create a node from the starting tile 'current'
n.init();
n.thisTile = &Map[current];
n.calculateCostToTile(Map[destination]); // Destination is stored in 'destination'
n.calculateCosts();

examineSet.push(n); // Add starting node to nodes to be checked
allNodes.push_back(n); // Add this tile to the list of all tiles

while (!examineSet.empty()) // While we have objects to check
{
n = examineSet.top(); // Get the best next node
doneSet.push_back(n); // Add it to the list of good nodes
examineSet.pop(); // Remove from list to be checked

if (doneSet.at(doneSet.size()-1).thisTile->ID == Map[destination].ID) //Goal?
{
goal = true;
break;
}

node near[4]; // List of neighbors, only 4 directions possible
int numOfNear = n.getNeighbors(near); // Find those neighbors

int thisOrd = 0; // The index of the current tile in the allNodes list
for (int z = 0;z < allNodes.size();z++) // Need to get a permanent reference to the node, in the allNodes list
{
if (allNodes.at(z).thisTile->ID == n.thisTile->ID)
{
thisOrd = z; // This is the index of the parent node
}
}

for (int i = 0,d = 0; i < numOfNear; i++) // Loop through the list
{
near.parent = thisOrd; // Set parent node relative to the allNodes list

for (int z = 0;z < doneSet.size()-1;z++) // Make sure we havent already checked this one
{
if (near.thisTile->ID == doneSet.at(z).thisTile->ID)
{
d = 1; // If we have set d to 1, or duplicate
break;
}
}
if (d == 1)
{
// If it is a duplicate, then reset the duplicate indicator and dont store this node
d = 0;
continue;
}

allNodes.push_back(near); // Add this node to the allNodes list, incase it is a parent

near.calculateCostToTile(Map[destination]); //Calculate cost to get to 'destination from here
near.calculateGCost(allNodes); // Pass it the allNodes list, so it can get its parent node
near.calculateCosts(); //Add parent g Cost and cost to goal

examineSet.push(near); //Add to list for checking
}
}

if (goal) // Have we suceeded this run?
{
cout << "Path to ramp found!\n";
// Extract the movement list from the parent tree
int moveOffset = thisMove.size();
n = doneSet.at(doneSet.size()-1); // Get the last item in the doneSet
do
{
thisMove.insert(thisMove.begin() + moveOffset,n.thisTile->ID); // Following the tree of parents, add them to the move_path
if (n.parent < 0 || n.parent > allNodes.size())
{
cout << "Parent issue at line 766\n";
cout << "I bet You're on a ramp, or clicked one.\n";
break;
}
else
n = allNodes.at(n.parent);
}
while (n.thisTile->ID != current);
// Done getting list of moves to get to 'destination'

if (thisMove[thisMove.size()-1] != move_destination)
{
if (layerChange == 0)
{
cout << "No Path Found\n";
return false;
}
// Set the current location to a different layer than the current one
current = destination + ((num_col_objects*num_row_objects)*(layerChange));
// Re-set the destination as the move_destination
destination = move_destination;
}
}
else
{
cout << "Couldn't find a path to the destination\n";
return false;
// In the future this would step back and say, "Ok, Lets try a different ramp!"
// As well as store the info that you can get to whatever layer from this ramp...
}

}
while (thisMove[thisMove.size()-1] != move_destination);

move_path = thisMove;

return true; //Succesfully calculated a path.
}
[/spoiler]

Many thanks to all that have helped me! And the advice I have been given ;)

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!