C++ debug/print custom type with GDB : the case of nlohmann json library












10















I'm working on a project using nlohmann's json C++ implementation.



How can one easily explore nlohmann's JSON keys/vals in GDB ?



I tried to use this STL gdb wrapping since it provides helpers to explore STL structures that lohmann's JSON lib is using.
But I don't find it convenient.



Here is a simple use case:



json foo;
foo["flex"] = 0.2;
foo["awesome_str"] = "bleh";
foo["nested"] = {{"bar", "barz"}};


What I would like to have in GDB:



(gdb) p foo
{
"flex" : 0.2,
"awesome_str": "bleh",
"nested": etc.
}


Current behavior



(gdb) p foo
$1 = {
m_type = nlohmann::detail::value_t::object,
m_value = {
object = 0x129ccdd0,
array = 0x129ccdd0,
string = 0x129ccdd0,
boolean = 208,
number_integer = 312266192,
number_unsigned = 312266192,
number_float = 1.5427999782486669e-315
}
}
(gdb) p foo.at("flex")
Cannot evaluate function -- may be inlined // I suppose it depends on my compilation process. But I guess it does not invalidate the question.
(gdb) p *foo.m_value.object
$2 = {
_M_t = {
_M_impl = {
<std::allocator<std::_Rb_tree_node<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long long, unsigned long long, double, std::allocator, nlohmann::adl_serializer> > > >> = {
<__gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long long, unsigned long long, double, std::allocator, nlohmann::adl_serializer> > > >> = {<No data fields>}, <No data fields>},
<std::_Rb_tree_key_compare<std::less<void> >> = {
_M_key_compare = {<No data fields>}
},
<std::_Rb_tree_header> = {
_M_header = {
_M_color = std::_S_red,
_M_parent = 0x4d72d0,
_M_left = 0x4d7210,
_M_right = 0x4d7270
},
_M_node_count = 5
}, <No data fields>}
}
}









share|improve this question

























  • You mean you don't find great joy manually digging through red/black trees to try and find something? ;)

    – Retired Ninja
    59 mins ago
















10















I'm working on a project using nlohmann's json C++ implementation.



How can one easily explore nlohmann's JSON keys/vals in GDB ?



I tried to use this STL gdb wrapping since it provides helpers to explore STL structures that lohmann's JSON lib is using.
But I don't find it convenient.



Here is a simple use case:



json foo;
foo["flex"] = 0.2;
foo["awesome_str"] = "bleh";
foo["nested"] = {{"bar", "barz"}};


What I would like to have in GDB:



(gdb) p foo
{
"flex" : 0.2,
"awesome_str": "bleh",
"nested": etc.
}


Current behavior



(gdb) p foo
$1 = {
m_type = nlohmann::detail::value_t::object,
m_value = {
object = 0x129ccdd0,
array = 0x129ccdd0,
string = 0x129ccdd0,
boolean = 208,
number_integer = 312266192,
number_unsigned = 312266192,
number_float = 1.5427999782486669e-315
}
}
(gdb) p foo.at("flex")
Cannot evaluate function -- may be inlined // I suppose it depends on my compilation process. But I guess it does not invalidate the question.
(gdb) p *foo.m_value.object
$2 = {
_M_t = {
_M_impl = {
<std::allocator<std::_Rb_tree_node<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long long, unsigned long long, double, std::allocator, nlohmann::adl_serializer> > > >> = {
<__gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long long, unsigned long long, double, std::allocator, nlohmann::adl_serializer> > > >> = {<No data fields>}, <No data fields>},
<std::_Rb_tree_key_compare<std::less<void> >> = {
_M_key_compare = {<No data fields>}
},
<std::_Rb_tree_header> = {
_M_header = {
_M_color = std::_S_red,
_M_parent = 0x4d72d0,
_M_left = 0x4d7210,
_M_right = 0x4d7270
},
_M_node_count = 5
}, <No data fields>}
}
}









share|improve this question

























  • You mean you don't find great joy manually digging through red/black trees to try and find something? ;)

    – Retired Ninja
    59 mins ago














10












10








10








I'm working on a project using nlohmann's json C++ implementation.



How can one easily explore nlohmann's JSON keys/vals in GDB ?



I tried to use this STL gdb wrapping since it provides helpers to explore STL structures that lohmann's JSON lib is using.
But I don't find it convenient.



Here is a simple use case:



json foo;
foo["flex"] = 0.2;
foo["awesome_str"] = "bleh";
foo["nested"] = {{"bar", "barz"}};


What I would like to have in GDB:



(gdb) p foo
{
"flex" : 0.2,
"awesome_str": "bleh",
"nested": etc.
}


Current behavior



(gdb) p foo
$1 = {
m_type = nlohmann::detail::value_t::object,
m_value = {
object = 0x129ccdd0,
array = 0x129ccdd0,
string = 0x129ccdd0,
boolean = 208,
number_integer = 312266192,
number_unsigned = 312266192,
number_float = 1.5427999782486669e-315
}
}
(gdb) p foo.at("flex")
Cannot evaluate function -- may be inlined // I suppose it depends on my compilation process. But I guess it does not invalidate the question.
(gdb) p *foo.m_value.object
$2 = {
_M_t = {
_M_impl = {
<std::allocator<std::_Rb_tree_node<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long long, unsigned long long, double, std::allocator, nlohmann::adl_serializer> > > >> = {
<__gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long long, unsigned long long, double, std::allocator, nlohmann::adl_serializer> > > >> = {<No data fields>}, <No data fields>},
<std::_Rb_tree_key_compare<std::less<void> >> = {
_M_key_compare = {<No data fields>}
},
<std::_Rb_tree_header> = {
_M_header = {
_M_color = std::_S_red,
_M_parent = 0x4d72d0,
_M_left = 0x4d7210,
_M_right = 0x4d7270
},
_M_node_count = 5
}, <No data fields>}
}
}









share|improve this question
















I'm working on a project using nlohmann's json C++ implementation.



How can one easily explore nlohmann's JSON keys/vals in GDB ?



I tried to use this STL gdb wrapping since it provides helpers to explore STL structures that lohmann's JSON lib is using.
But I don't find it convenient.



Here is a simple use case:



json foo;
foo["flex"] = 0.2;
foo["awesome_str"] = "bleh";
foo["nested"] = {{"bar", "barz"}};


What I would like to have in GDB:



(gdb) p foo
{
"flex" : 0.2,
"awesome_str": "bleh",
"nested": etc.
}


Current behavior



(gdb) p foo
$1 = {
m_type = nlohmann::detail::value_t::object,
m_value = {
object = 0x129ccdd0,
array = 0x129ccdd0,
string = 0x129ccdd0,
boolean = 208,
number_integer = 312266192,
number_unsigned = 312266192,
number_float = 1.5427999782486669e-315
}
}
(gdb) p foo.at("flex")
Cannot evaluate function -- may be inlined // I suppose it depends on my compilation process. But I guess it does not invalidate the question.
(gdb) p *foo.m_value.object
$2 = {
_M_t = {
_M_impl = {
<std::allocator<std::_Rb_tree_node<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long long, unsigned long long, double, std::allocator, nlohmann::adl_serializer> > > >> = {
<__gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long long, unsigned long long, double, std::allocator, nlohmann::adl_serializer> > > >> = {<No data fields>}, <No data fields>},
<std::_Rb_tree_key_compare<std::less<void> >> = {
_M_key_compare = {<No data fields>}
},
<std::_Rb_tree_header> = {
_M_header = {
_M_color = std::_S_red,
_M_parent = 0x4d72d0,
_M_left = 0x4d7210,
_M_right = 0x4d7270
},
_M_node_count = 5
}, <No data fields>}
}
}






c++ json gdb pretty-print nlohmann-json






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 1 hour ago







LoneWanderer

















asked 7 hours ago









LoneWandererLoneWanderer

1,122825




1,122825













  • You mean you don't find great joy manually digging through red/black trees to try and find something? ;)

    – Retired Ninja
    59 mins ago



















  • You mean you don't find great joy manually digging through red/black trees to try and find something? ;)

    – Retired Ninja
    59 mins ago

















You mean you don't find great joy manually digging through red/black trees to try and find something? ;)

– Retired Ninja
59 mins ago





You mean you don't find great joy manually digging through red/black trees to try and find something? ;)

– Retired Ninja
59 mins ago












1 Answer
1






active

oldest

votes


















14














I found my own answer reading further the GDB capabilities and stack overflow questions concerning print of std::string.



Short path



I simply defined a gdb command as follows:



# this is a gdb script
# can be loaded from gdb using
# source my_script.txt (or. gdb or whatever you like)
define pjson
# use the lohmann's builtin dump method, ident 4 and use space separator
printf "%sn", $arg0.dump(4, ' ', true).c_str()
end
# configure command helper (text displayed when typing 'help pjson' in gdb)
document pjson
Prints a lohmann's JSON C++ variable as a human-readable JSON string
end


Using it in gdb:



(gdb) source my_custom_script.gdb
(gdb) pjson foo
{
"flex" : 0.2,
"awesome_str": "bleh",
"nested": {
"bar": "barz"
}
}




Over the top



The other way is to define a GDB pretty printer in python and make it tightly associated to your project (autoloading stuff activated). See this link for an in-depth approach.



Basically, when in gdb you would type:



(gdb) p foo


and GDB will automagically test for foo's type and invoke the associated pretty printer if any. That would end-up in the same result. The main difference is that it is done using the well-known print command. The person debugging would not have to learn a new command (like the pjson defined in the short answer).



Quoting:




A pretty-printer consists of two parts: a lookup function to detect if the type is supported, and the printer itself.



Here is an example showing how a std::string printer might be written. See Pretty Printing API, for details on the API this class must provide.




class StdStringPrinter(object):
"Print a std::string"

def __init__(self, val):
self.val = val

def to_string(self):
return self.val['_M_dataplus']['_M_p']

def display_hint(self):
return 'string'


Still quoting for the sake of completness:




And here is an example showing how a lookup function for the printer example above might be written.




def str_lookup_function(val):
lookup_tag = val.type.tag
if lookup_tag == None:
return None
regex = re.compile("^std::basic_string<char,.*>$")
if regex.match(lookup_tag):
return StdStringPrinter(val)
return None





share|improve this answer

























    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55316620%2fc-debug-print-custom-type-with-gdb-the-case-of-nlohmann-json-library%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    14














    I found my own answer reading further the GDB capabilities and stack overflow questions concerning print of std::string.



    Short path



    I simply defined a gdb command as follows:



    # this is a gdb script
    # can be loaded from gdb using
    # source my_script.txt (or. gdb or whatever you like)
    define pjson
    # use the lohmann's builtin dump method, ident 4 and use space separator
    printf "%sn", $arg0.dump(4, ' ', true).c_str()
    end
    # configure command helper (text displayed when typing 'help pjson' in gdb)
    document pjson
    Prints a lohmann's JSON C++ variable as a human-readable JSON string
    end


    Using it in gdb:



    (gdb) source my_custom_script.gdb
    (gdb) pjson foo
    {
    "flex" : 0.2,
    "awesome_str": "bleh",
    "nested": {
    "bar": "barz"
    }
    }




    Over the top



    The other way is to define a GDB pretty printer in python and make it tightly associated to your project (autoloading stuff activated). See this link for an in-depth approach.



    Basically, when in gdb you would type:



    (gdb) p foo


    and GDB will automagically test for foo's type and invoke the associated pretty printer if any. That would end-up in the same result. The main difference is that it is done using the well-known print command. The person debugging would not have to learn a new command (like the pjson defined in the short answer).



    Quoting:




    A pretty-printer consists of two parts: a lookup function to detect if the type is supported, and the printer itself.



    Here is an example showing how a std::string printer might be written. See Pretty Printing API, for details on the API this class must provide.




    class StdStringPrinter(object):
    "Print a std::string"

    def __init__(self, val):
    self.val = val

    def to_string(self):
    return self.val['_M_dataplus']['_M_p']

    def display_hint(self):
    return 'string'


    Still quoting for the sake of completness:




    And here is an example showing how a lookup function for the printer example above might be written.




    def str_lookup_function(val):
    lookup_tag = val.type.tag
    if lookup_tag == None:
    return None
    regex = re.compile("^std::basic_string<char,.*>$")
    if regex.match(lookup_tag):
    return StdStringPrinter(val)
    return None





    share|improve this answer






























      14














      I found my own answer reading further the GDB capabilities and stack overflow questions concerning print of std::string.



      Short path



      I simply defined a gdb command as follows:



      # this is a gdb script
      # can be loaded from gdb using
      # source my_script.txt (or. gdb or whatever you like)
      define pjson
      # use the lohmann's builtin dump method, ident 4 and use space separator
      printf "%sn", $arg0.dump(4, ' ', true).c_str()
      end
      # configure command helper (text displayed when typing 'help pjson' in gdb)
      document pjson
      Prints a lohmann's JSON C++ variable as a human-readable JSON string
      end


      Using it in gdb:



      (gdb) source my_custom_script.gdb
      (gdb) pjson foo
      {
      "flex" : 0.2,
      "awesome_str": "bleh",
      "nested": {
      "bar": "barz"
      }
      }




      Over the top



      The other way is to define a GDB pretty printer in python and make it tightly associated to your project (autoloading stuff activated). See this link for an in-depth approach.



      Basically, when in gdb you would type:



      (gdb) p foo


      and GDB will automagically test for foo's type and invoke the associated pretty printer if any. That would end-up in the same result. The main difference is that it is done using the well-known print command. The person debugging would not have to learn a new command (like the pjson defined in the short answer).



      Quoting:




      A pretty-printer consists of two parts: a lookup function to detect if the type is supported, and the printer itself.



      Here is an example showing how a std::string printer might be written. See Pretty Printing API, for details on the API this class must provide.




      class StdStringPrinter(object):
      "Print a std::string"

      def __init__(self, val):
      self.val = val

      def to_string(self):
      return self.val['_M_dataplus']['_M_p']

      def display_hint(self):
      return 'string'


      Still quoting for the sake of completness:




      And here is an example showing how a lookup function for the printer example above might be written.




      def str_lookup_function(val):
      lookup_tag = val.type.tag
      if lookup_tag == None:
      return None
      regex = re.compile("^std::basic_string<char,.*>$")
      if regex.match(lookup_tag):
      return StdStringPrinter(val)
      return None





      share|improve this answer




























        14












        14








        14







        I found my own answer reading further the GDB capabilities and stack overflow questions concerning print of std::string.



        Short path



        I simply defined a gdb command as follows:



        # this is a gdb script
        # can be loaded from gdb using
        # source my_script.txt (or. gdb or whatever you like)
        define pjson
        # use the lohmann's builtin dump method, ident 4 and use space separator
        printf "%sn", $arg0.dump(4, ' ', true).c_str()
        end
        # configure command helper (text displayed when typing 'help pjson' in gdb)
        document pjson
        Prints a lohmann's JSON C++ variable as a human-readable JSON string
        end


        Using it in gdb:



        (gdb) source my_custom_script.gdb
        (gdb) pjson foo
        {
        "flex" : 0.2,
        "awesome_str": "bleh",
        "nested": {
        "bar": "barz"
        }
        }




        Over the top



        The other way is to define a GDB pretty printer in python and make it tightly associated to your project (autoloading stuff activated). See this link for an in-depth approach.



        Basically, when in gdb you would type:



        (gdb) p foo


        and GDB will automagically test for foo's type and invoke the associated pretty printer if any. That would end-up in the same result. The main difference is that it is done using the well-known print command. The person debugging would not have to learn a new command (like the pjson defined in the short answer).



        Quoting:




        A pretty-printer consists of two parts: a lookup function to detect if the type is supported, and the printer itself.



        Here is an example showing how a std::string printer might be written. See Pretty Printing API, for details on the API this class must provide.




        class StdStringPrinter(object):
        "Print a std::string"

        def __init__(self, val):
        self.val = val

        def to_string(self):
        return self.val['_M_dataplus']['_M_p']

        def display_hint(self):
        return 'string'


        Still quoting for the sake of completness:




        And here is an example showing how a lookup function for the printer example above might be written.




        def str_lookup_function(val):
        lookup_tag = val.type.tag
        if lookup_tag == None:
        return None
        regex = re.compile("^std::basic_string<char,.*>$")
        if regex.match(lookup_tag):
        return StdStringPrinter(val)
        return None





        share|improve this answer















        I found my own answer reading further the GDB capabilities and stack overflow questions concerning print of std::string.



        Short path



        I simply defined a gdb command as follows:



        # this is a gdb script
        # can be loaded from gdb using
        # source my_script.txt (or. gdb or whatever you like)
        define pjson
        # use the lohmann's builtin dump method, ident 4 and use space separator
        printf "%sn", $arg0.dump(4, ' ', true).c_str()
        end
        # configure command helper (text displayed when typing 'help pjson' in gdb)
        document pjson
        Prints a lohmann's JSON C++ variable as a human-readable JSON string
        end


        Using it in gdb:



        (gdb) source my_custom_script.gdb
        (gdb) pjson foo
        {
        "flex" : 0.2,
        "awesome_str": "bleh",
        "nested": {
        "bar": "barz"
        }
        }




        Over the top



        The other way is to define a GDB pretty printer in python and make it tightly associated to your project (autoloading stuff activated). See this link for an in-depth approach.



        Basically, when in gdb you would type:



        (gdb) p foo


        and GDB will automagically test for foo's type and invoke the associated pretty printer if any. That would end-up in the same result. The main difference is that it is done using the well-known print command. The person debugging would not have to learn a new command (like the pjson defined in the short answer).



        Quoting:




        A pretty-printer consists of two parts: a lookup function to detect if the type is supported, and the printer itself.



        Here is an example showing how a std::string printer might be written. See Pretty Printing API, for details on the API this class must provide.




        class StdStringPrinter(object):
        "Print a std::string"

        def __init__(self, val):
        self.val = val

        def to_string(self):
        return self.val['_M_dataplus']['_M_p']

        def display_hint(self):
        return 'string'


        Still quoting for the sake of completness:




        And here is an example showing how a lookup function for the printer example above might be written.




        def str_lookup_function(val):
        lookup_tag = val.type.tag
        if lookup_tag == None:
        return None
        regex = re.compile("^std::basic_string<char,.*>$")
        if regex.match(lookup_tag):
        return StdStringPrinter(val)
        return None






        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited 1 hour ago

























        answered 7 hours ago









        LoneWandererLoneWanderer

        1,122825




        1,122825
































            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55316620%2fc-debug-print-custom-type-with-gdb-the-case-of-nlohmann-json-library%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Statuo de Libereco

            Tanganjiko

            Liste der Baudenkmäler in Enneberg