如何在 gdb/lldb 调试中打印模板成员函数返回的值
how to print value returned by template member function in gdb/lldb debugging
OpenCV的classcv::Mat
中有一个名为at
的模板成员函数:
//definition of at
template<typename _Tp> inline const _Tp& Mat::at(int i0, int i1) const{
// ...
}
//my codes
cv::Mat eyePts_left;
// ...
if(std::max(eyePts_left.at<float>(0,0),eyePts_left.at<float>(16,0)) > eyePts_left.at<float>(61,0)){
//do something
}
我要打印表达式的值:
eyePts_left.at<float>(0,0)
在 lldb 调试会话中,但它抱怨:
(lldb) p eyePts_left.at<float>(0, 0)
error: warning: warning: got name from symbols: at
error: <user expression 21>:1:13: no member named 'at' in 'cv::Mat'
eyePts_left.at<float>(0, 0)
~~~~~~~~~~~ ^
error: <user expression 21>:1:21: expected '(' for function-style cast or type construction
eyePts_left.at<float>(0, 0)
~~~~~^
那么,检查这个与模板相关的表达式的值的正确方法是什么?
模板函数和模板化实体的当前调试信息通常很尴尬,因为它只描述实例化,而不是将模板描述为抽象实体,所以模板化函数只是显示在调试信息中,就像在某处带有尖括号的函数一样在名字中。这使得从调试信息到编译器表示变得棘手,lldb 可以将其输入到它的 clang 副本中,以便 clang 可以在表达式中正确解析它们。正如您所发现的,目前这不起作用。
但是,如果您真的需要这样做,您可以通过一些创造性的转换来解决这个问题,例如:
查找函数地址,例如
(lldb) image lookup -n Mat::at<float>
1 match found in /tmp/a.out:
Address: a.out[0x0000000100003f30] (a.out.__TEXT.__text + 64)
Summary: a.out`float const& Mat::at<float>(int, int) at template_fun.cpp:4
手动将呼叫投向该地址:
(lldb) expr ((float &(*) (Mat *, int, int))0x0000000100003f30)(&my_mat, 10, 20)
Called with 10 20
(float) [=11=] = 30
这不是你真正的功能,只是我做的一个玩具所以不要关注实际效果。
请注意,如果您最终经常这样做并且不是 100% 喜欢 C 函数转换语法,您可以在代码或 lldb 中为它创建一个 typedef,例如:
(lldb) expr typedef float &(*$Mat_at_type) (Mat *, int, int)
这简化了调用:
(lldb) expr (($Mat_at_type)0x0000000100003f30)(&my_mat, 10, 20)
Called with 10 20
(float) = 30
然后,如果您最终经常这样做,您甚至可以这样做:
(lldb) command alias call_at expr -- (($Mat_at_type)0x0000000100003f30)
(lldb) call_at (&my_mat, 10, 20)
OpenCV的classcv::Mat
中有一个名为at
的模板成员函数:
//definition of at
template<typename _Tp> inline const _Tp& Mat::at(int i0, int i1) const{
// ...
}
//my codes
cv::Mat eyePts_left;
// ...
if(std::max(eyePts_left.at<float>(0,0),eyePts_left.at<float>(16,0)) > eyePts_left.at<float>(61,0)){
//do something
}
我要打印表达式的值:
eyePts_left.at<float>(0,0)
在 lldb 调试会话中,但它抱怨:
(lldb) p eyePts_left.at<float>(0, 0)
error: warning: warning: got name from symbols: at
error: <user expression 21>:1:13: no member named 'at' in 'cv::Mat'
eyePts_left.at<float>(0, 0)
~~~~~~~~~~~ ^
error: <user expression 21>:1:21: expected '(' for function-style cast or type construction
eyePts_left.at<float>(0, 0)
~~~~~^
那么,检查这个与模板相关的表达式的值的正确方法是什么?
模板函数和模板化实体的当前调试信息通常很尴尬,因为它只描述实例化,而不是将模板描述为抽象实体,所以模板化函数只是显示在调试信息中,就像在某处带有尖括号的函数一样在名字中。这使得从调试信息到编译器表示变得棘手,lldb 可以将其输入到它的 clang 副本中,以便 clang 可以在表达式中正确解析它们。正如您所发现的,目前这不起作用。
但是,如果您真的需要这样做,您可以通过一些创造性的转换来解决这个问题,例如:
查找函数地址,例如
(lldb) image lookup -n Mat::at<float>
1 match found in /tmp/a.out:
Address: a.out[0x0000000100003f30] (a.out.__TEXT.__text + 64)
Summary: a.out`float const& Mat::at<float>(int, int) at template_fun.cpp:4
手动将呼叫投向该地址:
(lldb) expr ((float &(*) (Mat *, int, int))0x0000000100003f30)(&my_mat, 10, 20)
Called with 10 20
(float) [=11=] = 30
这不是你真正的功能,只是我做的一个玩具所以不要关注实际效果。
请注意,如果您最终经常这样做并且不是 100% 喜欢 C 函数转换语法,您可以在代码或 lldb 中为它创建一个 typedef,例如:
(lldb) expr typedef float &(*$Mat_at_type) (Mat *, int, int)
这简化了调用:
(lldb) expr (($Mat_at_type)0x0000000100003f30)(&my_mat, 10, 20)
Called with 10 20
(float) = 30
然后,如果您最终经常这样做,您甚至可以这样做:
(lldb) command alias call_at expr -- (($Mat_at_type)0x0000000100003f30)
(lldb) call_at (&my_mat, 10, 20)