Lon*_*rer 17 c++ json gdb pretty-print nlohmann-json
我正在使用nlohmann的json C ++实现进行项目开发。
如何在GDB中轻松浏览nlohmann的JSON键/值?
我尝试使用此STL gdb包装,因为它提供了帮助者探索nlohmann的JSON库正在使用的标准C ++库结构。但是我觉得不方便。
这是一个简单的用例:
json foo;
foo["flex"] = 0.2;
foo["awesome_str"] = "bleh";
foo["nested"] = {{"bar", "barz"}};
Run Code Online (Sandbox Code Playgroud)
我想在GDB中拥有什么:
(gdb) p foo
{
"flex" : 0.2,
"awesome_str": "bleh",
"nested": etc.
}
Run Code Online (Sandbox Code Playgroud)
当前行为
(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>}
}
}
Run Code Online (Sandbox Code Playgroud)
Lon*_*rer 23
我找到了自己的答案,进一步阅读了GDB功能以及有关打印std :: string的堆栈溢出问题。该短的路径是目前最好的选择。
短路径v3.1.2
我只是简单地定义了一个gdb命令,如下所示:
# 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 "%s\n", $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
Run Code Online (Sandbox Code Playgroud)
在gdb中使用它:
(gdb) source my_custom_script.gdb
(gdb) pjson foo
{
"flex" : 0.2,
"awesome_str": "bleh",
"nested": {
"bar": "barz"
}
}
Run Code Online (Sandbox Code Playgroud)
短路径v3.7.0 [编辑] 2019-onv-06 也可以使用新的to_string()方法,但是我无法通过较差的实时处理方法与GDB配合使用。下面的方法仍然有效。
# 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 "%s\n", $arg0.dump(4, ' ', true, json::error_handler_t::strict).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
Run Code Online (Sandbox Code Playgroud)
顶过(但不适合我)
另一种方法是在python中定义一个GDB 漂亮打印机,并使它与您的项目紧密关联(激活自动加载功能)。请参阅此链接以获取深入的方法。
基本上,在gdb中时,您将输入:
(gdb) p foo
Run Code Online (Sandbox Code Playgroud)
并且GDB会自动测试foo的类型,并调用关联的漂亮打印机(如果有)。最终结果会相同。主要区别在于它是使用众所周知的print命令完成的,而且更重要的是,即使没有劣等的方法来调用方法,该方法也有效(感谢Employed Russian的准确性)。调试人员不必学习新命令(如pjson简短答案中定义的命令)。
下面,一些GDB文档解压缩+ python代码尝试不起作用。
报价:
漂亮打印机由两部分组成:查找功能(用于检测是否支持该类型)和打印机本身。
这是显示如何
std::string写打印机的示例。有关此类必须提供的API的详细信息,请参见Pretty Printing API。
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'
Run Code Online (Sandbox Code Playgroud)
为了完整起见,仍在引用:
这是一个示例,显示了如何编写上述打印机示例的查找功能。
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
Run Code Online (Sandbox Code Playgroud)
我试图以这种方式实现它。但是,使用以下代码以及隐秘的GDB错误消息,我的失败率为100%(请参见下面的代码示例)
注意:它依赖于此处提供的技巧,该技巧应该允许GDB中的C ++类方法调用,而绕过Value.Type检查(可以找到对象方法,它们value.Type将是gdb.TYPE_CODE_METHOD,但是gdb python不会将它们视为可调用的。只能gdb.TYPE_CODE_FUNC被调用。因此,parse_and_eval充当执行实际方法调用的技巧。
import gdb
import re
class StdStringPrinter(object):
"""Print a std::string"""
def __init__(self, val):
self.val = val
def to_string(self):
eval_string = "(*("+str(self.val.type)+"*)("+str(self.val.address)+")).c_str()" # works 50% of the time ...
return gdb.parse_and_eval(eval_string)
def display_hint(self):
return 'string'
class LohmannJSONPrinter(object):
"""Print a nlohmann::json"""
def __init__(self, val):
self.val = val
def to_string(self):
# workaround from here:
# /sf/answers/1595863881/
# "(*("+str(self.val.type)+"*)("+str(self.val.address)+")).method()"
eval_string = '(*('+str(self.val.type)+'*)('+str(self.val.address)+')).dump(4, " ", true)'
return gdb.parse_and_eval(eval_string) # fails 100% of the time
def display_hint(self):
return self.val.type
def build_pretty_printer():
pp = gdb.printing.RegexpCollectionPrettyPrinter("foo")
json = r"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>"
pp.add_printer('nlohmann::json', json, LohmannJSONPrinter)
return pp
# executed at autoload gdb.printing.register_pretty_printer(gdb.current_objfile(),
build_pretty_printer())
Run Code Online (Sandbox Code Playgroud)
错误:
Cannot insert breakpoint -18. // or any negative value
Cannot access memory at address 0x111a2180 // appears to be a fixed value at each execution
Python Exception <class 'gdb.error'> Command aborted.
Run Code Online (Sandbox Code Playgroud)
要么
$2 = Python Exception <class 'gdb.error'> Attempt to take address of value not located in memory.:
Run Code Online (Sandbox Code Playgroud)
编辑2019年3月24日:增加受雇俄语提供的精度。
| 归档时间: |
|
| 查看次数: |
922 次 |
| 最近记录: |