Я пытаюсь отладить свою программу на C ++, которая является segfaulting.
Я проверил свой код, чтобы выяснить, могу ли я найти причину segfault.Я поместил несколько операторов cout
, чтобы сузить место, в котором произошла ошибка.
Я нашел вызов функции, которая вызывает ошибку сегмента.Это внутри функции обратного вызова.Это строка
inputbox->TestFunc();
, хотя для читателя это бессмысленно.
Это было подтверждено обратным следомв ГБД.(Я не мог получить более полезную информацию от GDB, кроме обратной трассировки, но я не слишком знаком с инструментами отладки.)
Я попытался создать MWE, и потерпел неудачу.Я потерпел неудачу, потому что, когда я сократил части кода для создания MWE, проблема ушла.(Так что я предполагаю, что это что-то тонкое, а не тривиальное.)
Я пытался написать MWE с нуля, копировать свои структуры наследования, но это не удалось.
Часть моей проблемы заключается в том, что я не могу просто удалить бит «xyz» кода, потому что это изменение одного аргумента функции нарушает множество другого кода из-за существующих структур наследования.
Я провел несколько других тестов, например, переместил «проблемную часть кода» в другие функции, такие как слой чуть ниже int main()
, и в этих местах, похоже, нет проблем.
Вызов inputbox->TestFunc2()
не завершается.TestFunc2()
не является переопределенной виртуальной функцией.TestFunc()
есть, и я думаю, что это может указывать на причину проблемы.(Хотя это и не напрямую, поскольку копирование структуры наследования в MWE устраняет проблему.)
Обе эти тестовые функции просто следят за именем функции и затем возвращают.Они ничего не читают и не записывают в память.
- Я некоторое время ничего не публиковал в SO, потому что не мог сформулировать вопрос таким способом, который мог бы получитькакой-то значимый ответ, однако некоторые поиски в Интернете предложили мне попытаться использовать valgrind для отладки проблемы.
С этим вот вывод valgrind
==8379== Memcheck, a memory error detector
==8379== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==8379== Using Valgrind-3.12.0.SVN and LibVEX; rerun with -h for copyright info
==8379== Command: ./a.out
==8379==
==8379== Conditional jump or move depends on uninitialised value(s)
==8379== at 0x4C32EA6: rawmemchr (vg_replace_strmem.c:1402)
==8379== by 0x5E8C3C1: _IO_str_init_static_internal (strops.c:41)
==8379== by 0x5E7FB96: vsscanf (iovsscanf.c:40)
==8379== by 0x5E7A306: sscanf (sscanf.c:32)
==8379== by 0xEC17E4A: ??? (in /usr/lib/x86_64-linux-gnu/libdrm.so.2.4.0)
==8379== by 0xEC18182: ??? (in /usr/lib/x86_64-linux-gnu/libdrm.so.2.4.0)
==8379== by 0xEC1BBF8: drmGetDevice (in /usr/lib/x86_64-linux-gnu/libdrm.so.2.4.0)
==8379== by 0xD7622D6: ??? (in /usr/lib/mesa-diverted/x86_64-linux-gnu/libGL.so.1.2.0)
==8379== by 0xD761694: ??? (in /usr/lib/mesa-diverted/x86_64-linux-gnu/libGL.so.1.2.0)
==8379== by 0xD735988: ??? (in /usr/lib/mesa-diverted/x86_64-linux-gnu/libGL.so.1.2.0)
==8379== by 0xD731B9A: ??? (in /usr/lib/mesa-diverted/x86_64-linux-gnu/libGL.so.1.2.0)
==8379== by 0xD731FD1: glXQueryExtensionsString (in /usr/lib/mesa-diverted/x86_64-linux-gnu/libGL.so.1.2.0)
==8379==
==8379== Syscall param writev(vector[...]) points to uninitialised byte(s)
==8379== at 0x5EF6E70: __writev_nocancel (syscall-template.S:84)
==8379== by 0x94BB41C: ??? (in /usr/lib/x86_64-linux-gnu/libxcb.so.1.1.0)
==8379== by 0x94BB81C: ??? (in /usr/lib/x86_64-linux-gnu/libxcb.so.1.1.0)
==8379== by 0x94BB89C: xcb_writev (in /usr/lib/x86_64-linux-gnu/libxcb.so.1.1.0)
==8379== by 0x6D6EA7D: _XSend (in /usr/lib/x86_64-linux-gnu/libX11.so.6.3.0)
==8379== by 0x6D6EF71: _XReply (in /usr/lib/x86_64-linux-gnu/libX11.so.6.3.0)
==8379== by 0x6D59E2E: XInternAtom (in /usr/lib/x86_64-linux-gnu/libX11.so.6.3.0)
==8379== by 0x4EFE46A: ??? (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.4.1)
==8379== by 0x4EFF364: ??? (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.4.1)
==8379== by 0x4EEF2EF: ??? (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.4.1)
==8379== by 0x4EEF07E: ??? (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.4.1)
==8379== by 0x4E55456: ??? (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.4.1)
==8379== Address 0xd1a9813 is 35 bytes inside a block of size 16,384 alloc'd
==8379== at 0x4C2DBC5: calloc (vg_replace_malloc.c:711)
==8379== by 0x6D5EEC5: XOpenDisplay (in /usr/lib/x86_64-linux-gnu/libX11.so.6.3.0)
==8379== by 0x4EFD53F: ??? (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.4.1)
==8379== by 0x4EEF02B: ??? (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.4.1)
==8379== by 0x4E55456: ??? (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.4.1)
==8379== by 0x10CF85: main (main.cpp:61)
==8379==
_ftm_ address: 0x12a0b610
SetPosition(0, 0)
Inputbox::TestFunc2()
Inputbox::TestFunc()
Inputbox::Draw()
0,0
SetPosition(0, 600)
refreshdelay set to: 16
ENTERED MAIN
SetPosition(0, 0)
Inputbox::TestFunc2()
Inputbox::TestFunc()
Inputbox::Draw()
derived2::function()
function was called ok
Window address: 0xffefffa00
Window 0
Window::TestFunc()
this=0xffefffa00
FontTextureManager::TestFunc()
this=0x12a0b610
current_window->_ftm_ address: 0x12a0b610
==8379== Conditional jump or move depends on uninitialised value(s)
==8379== at 0x4EEBA2D: ??? (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.4.1)
==8379== by 0x128278: Window::Height() const (Window.hpp:773)
==8379== by 0x12794E: fc_open(Window*) (FunctionCallback.cpp:133)
==8379== by 0x10D257: main (main.cpp:109)
==8379==
==8379== Use of uninitialised value of size 8
==8379== at 0x4EEBA32: ??? (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.4.1)
==8379== by 0x128278: Window::Height() const (Window.hpp:773)
==8379== by 0x12794E: fc_open(Window*) (FunctionCallback.cpp:133)
==8379== by 0x10D257: main (main.cpp:109)
==8379==
==8379== Use of uninitialised value of size 8
==8379== at 0x12827D: Window::Height() const (Window.hpp:774)
==8379== by 0x12794E: fc_open(Window*) (FunctionCallback.cpp:133)
==8379== by 0x10D257: main (main.cpp:109)
==8379==
==8379== Conditional jump or move depends on uninitialised value(s)
==8379== at 0x4EEBA23: ??? (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.4.1)
==8379== by 0x12823C: Window::Width() const (Window.hpp:766)
==8379== by 0x127966: fc_open(Window*) (FunctionCallback.cpp:133)
==8379== by 0x10D257: main (main.cpp:109)
==8379==
==8379== Use of uninitialised value of size 8
==8379== at 0x4EEBA28: ??? (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.4.1)
==8379== by 0x12823C: Window::Width() const (Window.hpp:766)
==8379== by 0x127966: fc_open(Window*) (FunctionCallback.cpp:133)
==8379== by 0x10D257: main (main.cpp:109)
==8379==
==8379== Use of uninitialised value of size 8
==8379== at 0x128241: Window::Width() const (Window.hpp:767)
==8379== by 0x127966: fc_open(Window*) (FunctionCallback.cpp:133)
==8379== by 0x10D257: main (main.cpp:109)
==8379==
SetPosition(400, 300)
INPUTBOX...
Inputbox::TestFunc2()
==8379== Invalid read of size 8
==8379== at 0x1279BF: fc_open(Window*) (FunctionCallback.cpp:136)
==8379== by 0x10D257: main (main.cpp:109)
==8379== Address 0x340 is not stack'd, malloc'd or (recently) free'd
==8379==
==8379==
==8379== Process terminating with default action of signal 11 (SIGSEGV)
==8379== Access not within mapped region at address 0x340
==8379== at 0x1279BF: fc_open(Window*) (FunctionCallback.cpp:136)
==8379== by 0x10D257: main (main.cpp:109)
==8379== If you believe this happened as a result of a stack
==8379== overflow in your program's main thread (unlikely but
==8379== possible), you can try to increase the size of the
==8379== main thread stack using the --main-stacksize= flag.
==8379== The main thread stack size used in this run was 8388608.
==8379==
==8379== HEAP SUMMARY:
==8379== in use at exit: 29,970,438 bytes in 46,548 blocks
==8379== total heap usage: 109,878 allocs, 63,330 frees, 61,448,020 bytes allocated
==8379==
==8379== LEAK SUMMARY:
==8379== definitely lost: 461,536 bytes in 124 blocks
==8379== indirectly lost: 176 bytes in 4 blocks
==8379== possibly lost: 28,306,879 bytes in 43,538 blocks
==8379== still reachable: 1,201,847 bytes in 2,882 blocks
==8379== suppressed: 0 bytes in 0 blocks
==8379== Rerun with --leak-check=full to see details of leaked memory
==8379==
==8379== For counts of detected and suppressed errors, rerun with: -v
==8379== Use --track-origins=yes to see where uninitialised values come from
==8379== ERROR SUMMARY: 23 errors from 9 contexts (suppressed: 0 from 0)
Segmentation fault
Появляется ключевая строкабыть Invalid read of size 8
at 0x1279BF: fc_open(Window*) (FunctionCallback.cpp:136)
Что означает эта информация и что я должен искать в своем коде, который мог вызвать эту ошибку?
Фрагмент кода:
void fc_open(Window *const current_window)
{
derived2 *object = new derived2;
object->function();
std::cout << "function was called ok" << std::endl;
std::cout << "Window address: " << current_window << std::endl;
std::cout << current_window->TestName() << std::endl;
current_window->TestFunc();
current_window->_ftm_->TestFunc();
std::cout << "current_window->_ftm_ address: " << current_window->_ftm_ << std::endl;
Inputbox *inputbox = new Inputbox(current_window->_ftm_);
std::cout << "inputbox=" << inputbox << std::endl;
inputbox->SetPosition(current_window->Width() / 2, current_window->Height() / 2);
std::cout << "INPUTBOX..." << std::endl;
inputbox->TestFunc2();
inputbox->TestFunc(); // BOOM
}