我正在使用 gdb 来调试我的 c++ 程序。我正在使用犰狳数值库来定义我的矩阵。我有一个这样定义的犰狳矩阵:
mat A = randu<mat>(5,5);
使用 gdb 调试器时是否可以打印整个矩阵?
这个问题可能是老问题,但绊倒它让我为自己的工作找到了解决方案。
由于 Armadillo 库基于模板的性质,您需要提供一些自己的帮助程序:
#include <iostream>
#include <armadillo>
template<class Matrix>
void print_matrix(Matrix matrix) {
matrix.print(std::cout);
}
//provide explicit instantiations of the template function for
//every matrix type you use somewhere in your program.
template void print_matrix<arma::mat>(arma::mat matrix);
template void print_matrix<arma::cx_mat>(arma::cx_mat matrix);
int main() {
arma::mat matrix = arma::randu(10,10);
return 0;
}
现在您可以轻松地print_matrix
从内部调用gdb
:
(gdb) call print_matrix<arma::Mat<double> >(matrix)
0.8402 0.4774 0.0163 0.5129 0.5267 0.5260 0.2383 0.5316 0.6879 0.9565
0.3944 0.6289 0.2429 0.8391 0.7699 0.0861 0.9706 0.0393 0.1660 0.5886
0.7831 0.3648 0.1372 0.6126 0.4002 0.1922 0.9022 0.4376 0.4401 0.6573
0.7984 0.5134 0.8042 0.2960 0.8915 0.6632 0.8509 0.9318 0.8801 0.8587
0.9116 0.9522 0.1567 0.6376 0.2833 0.8902 0.2667 0.9308 0.8292 0.4396
0.1976 0.9162 0.4009 0.5243 0.3525 0.3489 0.5398 0.7210 0.3303 0.9240
0.3352 0.6357 0.1298 0.4936 0.8077 0.0642 0.3752 0.2843 0.2290 0.3984
0.7682 0.7173 0.1088 0.9728 0.9190 0.0200 0.7602 0.7385 0.8934 0.8148
0.2778 0.1416 0.9989 0.2925 0.0698 0.4577 0.5125 0.6400 0.3504 0.6842
0.5540 0.6070 0.2183 0.7714 0.9493 0.0631 0.6677 0.3540 0.6867 0.9110
由于制表符完成,您只需要实际键入几个字符print_matrix<arma::Mat<double> >
.
最好的选择是使用 gdb 的 python API 为犰狳类创建漂亮的打印机。它比调用 C/C++ 函数更有效,因为它始终可以访问(即使从没有程序运行的核心文件进行调试)。此外,当您的程序中未使用该函数时,链接器不会有丢弃该函数的风险(从而在您在 gdb 中调试时使其不可用)。
.gdbinit
漂亮的打印机代码是从您的主文件夹中的文件加载(来源)的。它可以在终端和 IDE 中运行的 gdb 中工作(假设 IDE 不会避免加载.gdbinit
文件)。
例如,假设您有以下两个矩阵
arma::mat m1{{1.1, 2.2, 3},
{ 4, 5, 6},
{ 7, 8, 9},
{ 10, 11, 12},
{ 13, 14, 15},
{ 16, 17, 18}};
arma::cx_mat m2{{1.1 - 1.1j, 2.2 - 7.7j, 3},
{ 4, 5, 6},
{ 7, 8, 9},
{ 10, 11, 12},
{ 13, 14, 15},
{ 16, 17, 18}};
一台漂亮的打印机可能会将它们显示为
请注意复数矩阵m2
的元素如何以矩形形式和极坐标形式显示(可以禁用显示极坐标形式)。这也适用于 gdb 的其余部分。例如,gdb 允许您在数组中显示最大数量的元素。如果它被实现为在 gdb 中将元素显示为标准数组,那么漂亮的打印机将尊重这一点。
这就是CLion 中m1
和矩阵的显示方式。m2
这台漂亮的打印机可以从这里获得。还有一些其他的东西,比如一些xmethods(python 重新实现了一些 C++ 方法)和转换为 numpy 数组。
免责声明:我是这些漂亮打印机的作者。
最简单的方法是直接打印gdb
,可惜没有花哨的格式
> print *A.mem@5@5
$1 = {{0.84018771715470952, 0.39438292681909304,0.78309922375860586,0.79844003347607329, 0.91164735793678431},
{0.19755136929338396, 0.33522275571488902, 0.768229594811904, 0.27777471080318777, 0.55396995579543051},
{0.47739705186216025, 0.62887092476192441, 0.36478447279184334, 0.51340091019561551, 0.95222972517471283},
{0.91619506800370065, 0.63571172795990094, 0.71729692943268308, 0.14160255535580338, 0.60696887625705864},
{0.016300571624329581, 0.24288677062973696, 0.13723157678601872, 0.80417675422699042, 0.15667908925408455}}
您可以在 中调用 C 函数gdb
,因此您只需要一个打印对象的函数。例如:
(gdb) call printf("%.2f", 3.1428)
$7 = 4
(gdb) call fflush(stdout)
3.14$8 = 0
对于那些使用 QtCreator 的人,您可以通过使用 Python 调试助手扩展 GDB来检查 IDE 中的值(也许其他 IDE 也支持此功能)。
例如,将以下脚本放入~/debugHelpers.py
#!/usr/bin/python
import gdb # gdb.Value()
import dumper # dumper.Children()
def qdump__arma__Mat(d, value):
array = value["mem"]
cols = value["n_cols"]
rows = value["n_rows"]
maxDisplayItems = 50
innerType = d.templateArgument(value.type, 0)
p = gdb.Value(array.cast(innerType.pointer()))
d.putItemCount(cols)
d.putNumChild(cols)
if d.isExpanded():
numDisplayItems = min(maxDisplayItems, cols)
with dumper.Children(d, numChild=cols,
maxNumChild=numDisplayItems,
childType="<column>",
addrBase=p,
addrStep=p.dereference().__sizeof__):
for i in range(0, int(numDisplayItems)):
with dumper.Children(d):
d.putItemCount(rows)
d.putNumChild(rows)
if d.isExpanded():
numDisplayItems = min(maxDisplayItems, rows)
with dumper.Children(d, numChild=rows,
maxNumChild=numDisplayItems,
childType=innerType,
addrBase=p,
addrStep=p.dereference().__sizeof__):
for j in range(0, int(numDisplayItems)):
d.putSubItem(j, p.dereference())
p += 1
并称之为将此行添加到您的~/.gdbinit
:
python exec(open('/<full_path>/debugHelpers.py').read())
或从您的 IDE 中添加它;在 QtCreator 中使用 Tools > Options > Debugger > GDB (tab) > Extra Debugging Helpers (靠近底部)。
这个特定的脚本将返回按列排列的矩阵(我的架构中的自然内存排列):