[UT][Segmentation fault] problem with falling test

Hi,
I once made a project with UT in gtest, I got a lot of hel here and it’s worked I updated it, after gtest was updated, and I have a small problem. Tests Color_tester_view_test, PWM_chart_view_test.h pass but other controller tests have issue
local on windows: Program errored with 3221225477 code
CI (ubuntu): Program received signal SIGSEGV (Segmentation fault)
I think maybe sosmething wrong with view_mocks, I chagne from raw pointer to smart pointer in one test but it still isn’t work
this is my repostiory: GitHub - InzynierDomu/LED_tester: Simply device to help work with LEDs.
a here is error on CI: small clear · InzynierDomu/LED_tester@12dc911 · GitHub

Okay. So, build the test executable in debug mode (build_flags = -g3 -ggdb3) and run it in GDB. You will see a backtrace of the error where it crashed.

max@virtualbox:~/temp/LED_tester$ gdb .pio/build/UT/program 
GNU gdb (Ubuntu 14.0.50.20230907-0ubuntu1) 14.0.50.20230907-git
Copyright (C) 2023 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from .pio/build/UT/program...
(gdb) r
Starting program: /home/max/temp/LED_tester/.pio/build/UT/program 

This GDB supports auto-downloading debuginfo from the following URLs:
  <https://debuginfod.ubuntu.com>
Enable debuginfod for this session? (y or [n]) y
Debuginfod has been enabled.
To make this setting permanent, add 'set debuginfod enabled on' to .gdbinit.
Downloading separate debug info for system-supplied DSO at 0x7ffff7fc4000
Downloading separate debug info for /lib/x86_64-linux-gnu/libstdc++.so.6        
Downloading separate debug info for /lib/x86_64-linux-gnu/libgcc_s.so.1         
[Thread debugging using libthread_db enabled]                                   
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[==========] Running 13 tests from 5 test suites.
[----------] Global test environment set-up.
[----------] 4 tests from Color_tester_controller_test
[ RUN      ] Color_tester_controller_test.active

Program received signal SIGSEGV, Segmentation fault.
0x00005555555b7963 in testing::internal::UntypedFunctionMockerBase::RegisterOwner (this=0x8, mock_obj=0x0)
    at .pio/libdeps/UT/googletest/googlemock/src/gmock-spec-builders.cc:321
321	    mock_obj_ = mock_obj;
(gdb) where
#0  0x00005555555b7963 in testing::internal::UntypedFunctionMockerBase::RegisterOwner (this=0x8, mock_obj=0x0)
    at .pio/libdeps/UT/googletest/googlemock/src/gmock-spec-builders.cc:321
#1  0x00005555555677d9 in Color_tester::Color_tester_view_mock::gmock_print_screen (this=0x0)
    at test/../test/../test/mocks/Color_tester_view_mock.h:13
#2  0x00005555555654f1 in Color_tester::Color_tester_controller_test_active_Test::TestBody (this=0x55555569a3e0)
    at test/Color_tester_controller_test.cpp:13
#3  0x00005555555fbed4 in testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, void> (
    object=0x55555569a3e0, method=&virtual testing::Test::TestBody(), location=0x555555624a93 "the test body")
    at .pio/libdeps/UT/googletest/googletest/src/gtest.cc:2599
#4  0x00005555555f4fd7 in testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void> (
    object=0x55555569a3e0, method=&virtual testing::Test::TestBody(), location=0x555555624a93 "the test body")
    at .pio/libdeps/UT/googletest/googletest/src/gtest.cc:2635
#5  0x00005555555d58b4 in testing::Test::Run (this=0x55555569a3e0)
    at .pio/libdeps/UT/googletest/googletest/src/gtest.cc:2674
#6  0x00005555555d63b1 in testing::TestInfo::Run (this=0x555555697330)
    at .pio/libdeps/UT/googletest/googletest/src/gtest.cc:2853
#7  0x00005555555d6d05 in testing::TestSuite::Run (this=0x5555556978e0)
    at .pio/libdeps/UT/googletest/googletest/src/gtest.cc:3012
#8  0x00005555555e6f97 in testing::internal::UnitTestImpl::RunAllTests (this=0x555555697510)
    at .pio/libdeps/UT/googletest/googletest/src/gtest.cc:5870
#9  0x00005555555fd3b1 in testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool> (object=0x555555697510, 
    method=(bool (testing::internal::UnitTestImpl::*)(testing::internal::UnitTestImpl * const)) 0x5555555e6b7c <testing::internal::UnitTestImpl::RunAllTests()>, 
    location=0x555555625518 "auxiliary test code (environments or event listeners)")
    at .pio/libdeps/UT/googletest/googletest/src/gtest.cc:2599
#10 0x00005555555f616d in testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool> (object=0x555555697510, 
    method=(bool (testing::internal::UnitTestImpl::*)(testing::internal::UnitTestImpl * const)) 0x5555555e6b7c <testing::internal::UnitTestImpl::RunAllTests()>, 
    location=0x555555625518 "auxiliary test code (environments or event listeners)")
    at .pio/libdeps/UT/googletest/googletest/src/gtest.cc:2599
#10 0x00005555555f616d in testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool> (object=0x555555697510, 
    method=(bool (testing::internal::UnitTestImpl::*)(testing::internal::UnitTestImpl * const)) 0x5555555e6b7c <testing::internal::UnitTestImpl::RunAllTests()>, 
    location=0x555555625518 "auxiliary test code (environments or event listeners)") at .pio/libdeps/UT/googletest/googletest/src/gtest.cc:2635
#11 0x00005555555e5545 in testing::UnitTest::Run (this=0x555555684640 <testing::UnitTest::GetInstance()::instance>)
    at .pio/libdeps/UT/googletest/googletest/src/gtest.cc:5444
#12 0x00005555555b46d7 in RUN_ALL_TESTS () at .pio/libdeps/UT/googletest/googletest/include/gtest/gtest.h:2293
#13 0x00005555555b4650 in main (argc=1, argv=0x7fffffffde48) at test/ut_main.cpp:6

Specifically

(gdb) p mock_obj
$1 = (const void *) 0x0
(gdb) p mock_obj_
Cannot access memory at address 0x10

You can also debug this in VSCode itself by setting

debug_test = *

as documented. Then, execution of the PIO Debug task will land in main() of the test binary and then in the crash.

1 Like

This code is bs.

In C++, the members will be initialized in alphabetical order (source). Despite you writing view_mock(new Color..) first, it is actually the last statement to be executed, and it will first try to initialize uut.

A B C D E F ... Q R S T U V W

This leaves uut wrongly initialized.

Same thing with

PWM_chart_controller_test::PWM_chart_controller_test()
: hal_mock{}
, view_mock{}
, uut(hal_mock, model, &view_mock)
{}

The next error is moving a unique pointer with std::move to some other place and then still accessing the old pointer. The old one becomes invalid (0x000000000).

Then, the PWM_chart_controller tries to delete m_view even though it was not allocated dynamically with new. That crashes with free(): invalid pointer. For simplicity, I turned this into a raw pointer that is new’ed. Same goes for the PWM_controller_test.

Fixing up all these mistakes, we finally arrive at

See

1 Like

Thanks! I know gdb, but I haven’t used it in a configuration with such a toolchain yet, I’ll try it out and thanks for pointing out the bug :grinning: