vscode-cpptools icon indicating copy to clipboard operation
vscode-cpptools copied to clipboard

GDB pretty-printing of unordered_map<std::type_index, T> crashes connection to debugger

Open rjra100 opened this issue 5 years ago • 7 comments

Issue Type: Bug

To reproduce:

  • Compile (with debug info) any code including a std::unordered_map containing std::type_index. For example:
#include <unordered_map>
#include <typeindex>

int main() {
    int x=5;
    std::unordered_map<std::type_index, int> m {
        { typeid(int), 1 },
        { typeid(double), 2}
    };
    return 0;
}
  • Put a breakpoint after the map has some data in it (the return line above)
  • Set up a launch.json similar to this:
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "g++ - Build and debug active file",
            "type": "cppdbg",
            "request": "launch",
            "program": "<path to exe>",
            "args": [],
            "stopAtEntry": false,
            "cwd": "${workspaceFolder}",
            "environment": [],
            "externalConsole": false,
            "MIMode": "gdb",
            "miDebuggerPath": "/opt/rh/devtoolset-7/root/usr/bin/gdb",
            "setupCommands": [
                {
                    "description": "Enable pretty-printing for gdb",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": false
                }
            ]
        }
    ]
}
  • Launch the debugger. At the breakpoint, look at the variables (in the variables or watch window, or by hovering).

Actual behaviour: as soon as an attempt is made to visualise the map, the debug session crashes, giving Stopping due to fatal error: NullReferenceException: Object reference not set to an instance of an object in the Debug console.

Expected behaviour: we get a visualisation of the map.

Detailed log output:

<--   C (variables-16): {"command":"variables","arguments":{"variablesReference":1003},"type":"request","seq":16}
--> E (output): {"type":"event","event":"output","body":{"category":"console","output":"1: (48954) <-1029-var-list-children --simple-values \"var2\" 0 1000\n"},"seq":470}
1: (48954) <-1029-var-list-children --simple-values "var2" 0 1000
--> E (output): {"type":"event","event":"output","body":{"category":"console","output":"1: (48955) ->1029^done,numchild=\"4\",displayhint=\"map\",children=[child={name=\"var2.[0]\",exp=\"[0]\",numchild=\"1\",type=\"const std::type_index\",thread-id=\"1\"},child={name=\"var2.[1]\",exp=\"[1]\",numchild=\"0\",value=\"2\",type=\"int\",thread-id=\"1\"},child={name=\"var2.[2]\",exp=\"[2]\",numchild=\"1\",type=\"const std::type_index\",thread-id=\"1\"},child={name=\"var2.[3]\",exp=\"[3]\",numchild=\"0\",value=\"1\",type=\"int\",thread-id=\"1\"}],has_more=\"0\"\n"},"seq":472}
1: (48955) ->1029^done,numchild="4",displayhint="map",children=[child={name="var2.[0]",exp="[0]",numchild="1",type="const std::type_index",thread-id="1"},child={name="var2.[1]",exp="[1]",numchild="0",value="2",type="int",thread-id="1"},child={name="var2.[2]",exp="[2]",numchild="1",type="const std::type_index",thread-id="1"},child={name="var2.[3]",exp="[3]",numchild="0",value="1",type="int",thread-id="1"}],has_more="0"
--> E (output): {"type":"event","event":"output","body":{"category":"console","output":"1: (48955) ->(gdb)\n"},"seq":474}
1: (48955) ->(gdb)
--> E (output): {"type":"event","event":"output","body":{"category":"console","output":"1: (48955) 1029: elapsed time 1\n"},"seq":476}
1: (48955) 1029: elapsed time 1
Stopping due to fatal error: NullReferenceException: Object reference not set to an instance of an object

For comparison, if I run -exec p m, I get

-exec p m
<--   C (evaluate-13): {"command":"evaluate","arguments":{"expression":"-exec p m","frameId":1000,"context":"repl"},"type":"request","seq":13}
--> E (output): {"type":"event","event":"output","body":{"category":"console","output":"1: (10589) <-1028-interpreter-exec console \"p m\"\n"},"seq":435}
1: (10589) <-1028-interpreter-exec console "p m"
--> E (output): {"type":"event","event":"output","body":{"category":"console","output":"1: (10590) ->~\"$1 = std::unordered_map with 2 elements = {[{_M_target = 0x604dc0 <typeinfo for double@@CXXABI_1.3>\"\n"},"seq":437}
1: (10590) ->~"$1 = std::unordered_map with 2 elements = {[{_M_target = 0x604dc0 <typeinfo for double@@CXXABI_1.3>"
--> E (output): {"type":"event","event":"output","body":{"category":"console","output":"1: (10590) ->~\"}\"\n"},"seq":439}
1: (10590) ->~"}"
--> E (output): {"type":"event","event":"output","body":{"category":"console","output":"1: (10591) ->~\"] = 2\"\n"},"seq":441}
1: (10591) ->~"] = 2"
--> E (output): {"type":"event","event":"output","body":{"category":"console","output":"1: (10591) ->~\", [{_M_target = 0x604de0 <typeinfo for int@@CXXABI_1.3>\"\n"},"seq":443}
1: (10591) ->~", [{_M_target = 0x604de0 <typeinfo for int@@CXXABI_1.3>"
--> E (output): {"type":"event","event":"output","body":{"category":"console","output":"1: (10591) ->~\"}\"\n"},"seq":445}
1: (10591) ->~"}"
--> E (output): {"type":"event","event":"output","body":{"category":"console","output":"1: (10591) ->~\"] = 1\"\n"},"seq":447}
1: (10591) ->~"] = 1"
--> E (output): {"type":"event","event":"output","body":{"category":"console","output":"1: (10591) ->~\"}\\n\"\n"},"seq":449}
1: (10591) ->~"}\n"
--> E (output): {"type":"event","event":"output","body":{"category":"console","output":"1: (10591) ->1028^done\n"},"seq":451}
1: (10591) ->1028^done
--> E (output): {"type":"event","event":"output","body":{"category":"console","output":"1: (10591) ->(gdb)\n"},"seq":453}
1: (10591) ->(gdb)
--> E (output): {"type":"event","event":"output","body":{"category":"console","output":"1: (10591) 1028: elapsed time 1\n"},"seq":455}
1: (10591) 1028: elapsed time 1
--> E (output): {"type":"event","event":"output","body":{"category":"stdout","output":"$1 = std::unordered_map with 2 elements = {[{_M_target = 0x604dc0 <typeinfo for double@@CXXABI_1.3>}] = 2, [{_M_target = 0x604de0 <typeinfo for int@@CXXABI_1.3>}] = 1}\n\n"},"seq":457}
$1 = std::unordered_map with 2 elements = {[{_M_target = 0x604dc0 <typeinfo for double@@CXXABI_1.3>}] = 2, [{_M_target = 0x604de0 <typeinfo for int@@CXXABI_1.3>}] = 1}

--> E (output): {"type":"event","event":"output","body":{"category":"telemetry","output":"VS/Diagnostics/Debugger/Evaluate","data":{"VS.Diagnostics.Debugger.ImplementationName":"Microsoft.MIDebugEngine","VS.Diagnostics.Debugger.EngineVersion":"16.5.11030.1","VS.Diagnostics.Debugger.HostVersion":"16.5.11030.1","VS.Diagnostics.Debugger.AdapterId":"cppdbg","VS.Diagnostics.Debugger.Evaluate.Duration":5.0,"VS.Diagnostics.Debugger.Evaluate.IsError":false,"VS.Diagnostics.Debugger.Evaluate.ExecuteInConsole":true}},"seq":459}
--> R (evaluate-13): {"type":"response","request_seq":13,"success":true,"command":"evaluate","body":{"result":"","variablesReference":0},"seq":461}
<--   C (scopes-14): {"command":"scopes","arguments":{"frameId":1000},"type":"request","seq":14}
--> R (scopes-14): {"type":"response","request_seq":14,"success":true,"command":"scopes","body":{"scopes":[{"name":"Locals","variablesReference":1002,"expensive":false}]},"seq":464}
<--   C (variables-15): {"command":"variables","arguments":{"variablesReference":1002},"type":"request","seq":15}
--> R (variables-15): {"type":"response","request_seq":15,"success":true,"command":"variables","body":{"variables":[{"name":"x","value":"5","type":"int","evaluateName":"x","variablesReference":0,"memoryReference":"0x0000000000000005"},{"name":"m","value":"{...}","type":"std::unordered_map<std::type_index, int, std::hash<std::type_index>, std::equal_to<std::type_index>, std::allocator<std::pair<std::type_index const, int> > >","evaluateName":"m","variablesReference":1003}]},"seq":467}

Extension version: 1.1.2 VS Code version: Code 1.51.1 (e5a624b788d92b8d34d1392e4c4d9789406efe8f, 2020-11-10T23:34:32.027Z) OS version: Windows_NT x64 10.0.19041 Remote OS version: Linux x64 4.19.104-microsoft-standard Remote OS version: Linux x64 4.19.104-microsoft-standard

Also reproduced on Linux in VSCode 1.49.3 (same extension version; in this case the only other extension was CMake Tools).

rjra100 avatar Nov 26 '20 17:11 rjra100

Thank you for reporting this issue, we will investigate this bug.

WardenGnaw avatar Nov 30 '20 19:11 WardenGnaw

I can reproduce and fixed the crash but for some reason MIENgine does not display unordered_map<type_index, int> correctly.

Actual: image

1: (4386) <-1039-var-create - * "m"
1: (4465) ->1039^done,name="var8",numchild="0",value="{...}",type="std::unordered_map<std::type_index, int, std::hash<std::type_index>, std::equal_to<std::type_index>, std::allocator<std::pair<std::type_index const, int> > >",thread-id="1",displayhint="map",dynamic="1",has_more="1"

1: (7183) <-1042-var-list-children --simple-values "var8" 0 1000
1: (7193) ->1042^done,numchild="4",displayhint="map",children=[child={name="var8.[0]",exp="[0]",numchild="1",type="const std::type_index",thread-id="1"},child={name="var8.[1]",exp="[1]",numchild="0",value="2",type="int",thread-id="1"},child={name="var8.[2]",exp="[2]",numchild="1",type="const std::type_index",thread-id="1"},child={name="var8.[3]",exp="[3]",numchild="0",value="1",type="int",thread-id="1"}],has_more="0"

WardenGnaw avatar Nov 30 '20 22:11 WardenGnaw

Also meet this problem, when attach a remote process id using gdb: vscode version: 1.51.1 c++tools Extension version: 1.1.3 OS version: macos 10.14.6 Remote OS version: ubuntu 18.04.1 Remote gdb version: 8.1.0.20180409-git

xray1111 avatar Dec 12 '20 12:12 xray1111

Hi, I am getting a similar issue with unordered_map<neuron*, double> where neuron is a custom defined class. Below is the gif of the problem I am getting.

c++_debug_error2

Here, m_prev_layer_weights is the unorderd_map.

My VScode version: 1.52.1 ea3859d4ba2f3e577a159bc91e3074c5d85c0523 x64 Extension Version: 1.1.3 OS: Ubuntu 20.04

Srijan1214 avatar Jan 08 '21 03:01 Srijan1214

Same issue with a std::map, where K and V are custom structs.

ruabmbua avatar Jan 19 '21 13:01 ruabmbua

Also seeing this. Is it an issue in cpptools or in the MIEngine? The exception looks like a .Net one, so I assumed MIEngine, but I see no issue filed there.

ddurschlag avatar Apr 21 '21 22:04 ddurschlag

for me, it is due to a concurrency situation, after make it sequential, the problem solved.

std::map is not current safe

ddwolf avatar Sep 02 '22 02:09 ddwolf