Я пишу интерпретатор CHIP-8 в C ++ с SDL2. Исходный код находится на https://github.com/robbie0630/Chip8Emu. Существует проблема, когда возникает ошибка сегментации с этот ROM. Я пытался отладить проблему с GDB, но когда я набираю bt
, он отображает неполную трассировку стека, показывая только две верхние функции, что не позволяет мне эффективно диагностировать проблему. Как получить полную и полезную трассировку стека?
РЕДАКТИРОВАТЬ: Когда я бегу bt
, GDB отображает это:
#0 0x0000000101411a14 in ?? ()
#1 0x0000000000406956 in Chip8_CPU::doCycle (this=0x7fffffffc7b0) at /my/home/code/Chip8Emu/src/cpu.cpp:223
#2 0x0000000000402080 in main (argc=2, argv=0x7fffffffe108) at /my/home/code/Chip8Emu/src/main.cpp:152
Это бесполезно, потому что ??
ничего не указывает, а строка 223 cpu.cpp
это вызов функции.
РЕДАКТИРОВАТЬ 2: я запустил valgrind на программу, и вот вывод:
==11791== Conditional jump or move depends on uninitialised value(s)
==11791== at 0x406BA0: Chip8_CPU::doCycle() (cpu.cpp:215)
==11791== by 0x4020EF: main (main.cpp:152)
==11791==
==11791== Jump to the invalid address stated on the next line
==11791== at 0x101411A74: ???
==11791== by 0x4020EF: main (main.cpp:152)
==11791== Address 0x101411a74 is not stack'd, malloc'd or (recently) free'd
==11791==
==11791==
==11791== Process terminating with default action of signal 11 (SIGSEGV)
==11791== Access not within mapped region at address 0x101411A74
==11791== at 0x101411A74: ???
==11791== by 0x4020EF: main (main.cpp:152)
==11791== If you believe this happened as a result of a stack
==11791== overflow in your program's main thread (unlikely but
==11791== possible), you can try to increase the size of the
==11791== main thread stack using the --main-stacksize= flag.
==11791== The main thread stack size used in this run was 8388608.
==11791==
==11791== HEAP SUMMARY:
==11791== in use at exit: 7,827,602 bytes in 41,498 blocks
==11791== total heap usage: 169,848 allocs, 128,350 frees, 94,139,303 bytes allocated
==11791==
==11791== LEAK SUMMARY:
==11791== definitely lost: 0 bytes in 0 blocks
==11791== indirectly lost: 0 bytes in 0 blocks
==11791== possibly lost: 4,056,685 bytes in 36,878 blocks
==11791== still reachable: 3,770,917 bytes in 4,620 blocks
==11791== suppressed: 0 bytes in 0 blocks
==11791== Rerun with --leak-check=full to see details of leaked memory
==11791==
==11791== For counts of detected and suppressed errors, rerun with: -v
==11791== Use --track-origins=yes to see where uninitialised values come from
==11791== ERROR SUMMARY: 12 errors from 3 contexts (suppressed: 0 from 0)
Killed
РЕДАКТИРОВАТЬ 3: я снова запустил GDB, на этот раз смотреть GfxDraw
и я заметил, что это случилось:
Old value = (void (*)(array2d)) 0x1411bc4
New value = (void (*)(array2d)) 0x101411bc4
Chip8_CPU::doCycle (this=0x7fffffffc7a0) at /home/robbie/code/Chip8Emu/src/cpu.cpp:213
(gdb) cont
Continuing.
Thread 1 "Chip8Emu" received signal SIGSEGV, Segmentation fault.
0x0000000101411bc4 in ?? ()
Так как-то GfxDraw
изменяется на недопустимый указатель на функцию. Однако я не могу понять, где это модифицируется.
Через несколько месяцев я наконец-то определил проблему. Некоторые неприятные программы CHIP-8 делают недопустимый доступ к памяти графической памяти, находящейся за пределами массива и испорченных свойств процессора (таких как GfxDraw
). Я исправил эту проблему путем доступа к графической памяти с at
и игнорируя std::out_of_range
ошибки. Кажется, сейчас работает, поэтому я объявляю это решением.
Других решений пока нет …