Search code examples
visual-studio-codedebugginggdb

Inlined function C++ debugging


When I debug and type some value in evaluate expression box. I got this error "Cannot evaluate function -- may be inlined". Could anyone can tell me how can I do evaluate some object properties in evaluate expression box. Hug thanks!

I have searched all page related to this problem and all of them tell that it's impossible because GBD compiler optimization feature. But I want to ask all of you once more.

Here is my C++ code:

#include <bits/stdc++.h>
using namespace std;
int main()
{
    stack<int> the_stack = stack<int>({1, 2, 3});
    return 0;
}

In my example, how can I type "the_stack.size()" or "the_stack.top()" in evaluate expression box then I get the expected value.

My build command config:

       {
      "label": "build",
      "type": "shell",
      "command": "g++",
      "args": ["-O0", "${file}", "-g", "-o", "${workspaceFolder}/build/${fileBasenameNoExtension}"],
      "group": {
        "kind": "build",
        "isDefault": true
      }
}

Solution

  • You are not using the_stack.size() in your code and the_stack is an instance based on a template, so the member functions you're not using will most probably not exist in the binary.

    Just try return the_stack.size(); instead of return 0; (just to use the member function) and then run the debugger and do p the_stack.size(); after stepping over the initialization.

    Possible output:

    Reading symbols from stack...
    (gdb) start
    Temporary breakpoint 1, main () at stack.cpp:5
    5           stack<int> the_stack = stack<int>({1, 2, 3});
    (gdb) p the_stack.size()
    $1 = 18446744073643061723
    (gdb) n
    6           return the_stack.size();
    (gdb) p the_stack.size()
    $2 = 3
    (gdb)
    

    You could force the instantiation of the std::stack<int> class early to generate the member functions. It's not very nice for production code, but perhaps you'll find it useful:

    #include <stack>
    
    template class std::stack<int>; // explicit instantiation
    
    int main()
    {
        std::stack<int> the_stack = std::stack<int>({1, 2, 3});
        return 0;
    }
    

    Note that this only instantiates std::stack<int>. If you later add std::stack<double>, it'll have to be explicitly instantiated too in order for the unused member functions to become available.


    Without explicitly instantiating std::stack<int>, you could instead use one of the Xmethods defined for std::deque.

    (gdb) info xmethod
    ...
      libstdc++::deque
        empty
        size
        front
        back
        operator[]
        at
    ...
    

    In order to use one of these methods, you'll have to lookup (p the_stack. + tab + tab) the name of the member variable in the std::stack implementation you are using. In my implementation it's c, so:

    (gdb) p the_stack.        (tab + tab)
    c       empty   pop     push    size    stack   swap    top     ~stack
    (gdb) p the_stack.c
    $4 = std::deque with 3 elements = {1, 2, 3}
    (gdb) p the_stack.c.size()
    $2 = 3