Sewbacca
Sewbacca

Reputation: 666

gdb (MinGW) doesn't break on failed asserts (VSCode config)

I'm trying to debug a program, in VSCode, which violates an assert, but doesn't break and doesn't allow me to inspect the callstack or anything. Instead the program just exits with exitcode 3 and prints out the following text:

Assertion failed!

Program: C:\Users\Sewbacca\Projects\Practice\CppTest\build\Test.exe
File: C:\Users\Sewbacca\Projects\Practice\CppTest\src\main.cpp, Line 6

Expression: false

I tried to add the following commands to "setupCommands" in .vscode/launch.json with no success:

{
    "text": "break _assert (const char *_Message, const char *_File, unsigned _Line)"
},
{
    "text": "break abort"
},
{
    "text": "break exit"
},

Sidenote: I'm not experienced with gdb and I don't know exactly what setupCommands does change. I would have expected that vscode send these to gdb directly.

My only workarround is to set a breakpoint before main() and type -exec break abort into the debug console. Then it will break on any failed asserts.

Edit: Adding the following config to "setupCommands":

{
    "text": "-exec break abort"
},

Resulted in following error message:

[Window Title]
Visual Studio Code

[Content]
Unable to start debugging. Unexpected GDB output from command "-exec break abort". Undefined MI command: exec

[Open 'launch.json'] [Cancel]

End of Edit

Is there a way to automate this or is there a proper way to tell gdb (especially in VSCode) to break on failed asserts, rather than just exit the program?

Edit:

There was nothing wrong with my configuration. It seems like my gdb version was buggy. Sometimes it exited randomly when I told gdb to break before entering main, which led me to this issue. As stated there, gdb 8.1 for x86_64-w64-mingw32 has this bug. Since there is no newer version available in the installer, I downgraded to 7.2 which solved this issue for me. However, after using winlibs version 11.1.0, the issue still persists.

End of edit

Thanks in advance!

Setup:

src/main.cpp


#include <cassert>

int main()
{
    assert(false);
}

CMakeLists.txt

project(Test)

add_executable(${PROJECT_NAME} src/main.cpp)

.vscode/launch.json

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "(gdb) Launch",
            "type": "cppdbg",
            "request": "launch",
            // Resolved by CMake Tools:
            "program": "${command:cmake.launchTargetPath}",
            "args": [],
            "stopAtEntry": false,
            "cwd": "${workspaceFolder}",
            "environment": [
                {
                    // add the directory where our target was built to the PATHs
                    // it gets resolved by CMake Tools:
                    "name": "PATH",
                    "value": "${env:PATH}:${command:cmake.getLaunchTargetDirectory}"
                }
            ],
            "MIMode": "gdb",
            "setupCommands": [
                {
                    "description": "Enable pretty-printing for gdb",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true
                },
                {
                    "text": "break _assert (const char *_Message, const char *_File, unsigned _Line)"
                },
                {
                    "text": "break abort"
                },
                {
                    "text": "break exit"
                },
            ]
        }
    ],
    "compounds": []
}

My Environment:

Upvotes: 1

Views: 1032

Answers (1)

Sewbacca
Sewbacca

Reputation: 666

I found a solution:

gdb breaks on failed asserts, when adding the following code to setupCommands in launch.json:

"setupCommands": {
...
    {
        "text": "set breakpoint pending on",
        "description": "Ensures that a breakpoint for abort will be set!",
        "ignoreFailures": true
    },
    {
        "text": "break abort",
        "description": "Breaks on failed asserts",
        "ignoreFailures": true
    },
    {
        "text": "set breakpoint pending auto",
        "description": "Setting back to default behaviour",
        "ignoreFailures": true
    }
...
}

Explaination:

To break on assert failures, I found this Stack Overflow Post, which worked, when I tested it manually, but not when I used it in launch.json. I don't understand why it doesn't break on its own, but I do understand why break abort didn't worked, at least I have a guess: The symbols haven't been loaded yet and break abort asks you in gdb, if a pending breakpoint should be created, which defaults to no. So setting pending breakpoints to on, solved this issue for me and now I can finally debug my program.

Upvotes: 3

Related Questions