通过GDB打印闪电战阵列 [英] printing blitz arrays via GDB

查看:148
本文介绍了通过GDB打印闪电战阵列的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

最近几天我一直在使用Blitz阵列软件包. 在调试期间,我需要打印数组内容,而blitz支持以下内容

I have been using Blitz array package last few days. During debug I require to print the array contents, and blitz supports something like below

std::cout<<blitz_array_name<<std::endl

我想在调试过程中通过GDB打印数组内容. 所以我为不同类型的数组编写了重载函数,如下所示.

I would like to print the array contents via GDB during debug. So i wrote overloaded functions for different type of arrays which I like to prin, like below

void printBlitz(blitz::Array<bool, 1> &in)
{
std::cout<<in<<std::endl;
}

void printBlitz(blitz::Array<int, 1> &in)
{
std::cout<<in<<std::endl;
}

... and so on

在gdb调试器上,我可以简单地按以下方式调用此函数

on the gdb debugger, I can simply call this function as below

(gdb) call printBlitz(blitz_array_name)

  1. 现在的问题是我正在使用许多类型的多维数组,我必须对每个数组进行重载
  2. 我无法通过GDB的调用功能来调用模板函数-这也有帮助
  3. 我试图做以下类似的事情

(gdb)定义printmyvar 呼叫(void)operator<<(std :: cout,$ arg0) 打印"\ n" 结束

(gdb) define printmyvar call (void)operator<<(std::cout, $arg0) print "\n" end

当我尝试如下打印数组时

when i try to print the array as below

(gdb) printmyvar blitz_array_name

我收到此错误无法将函数运算符<<解析为任何重载实例"

I get this error "Cannot resolve function operator<< to any overloaded instance"

d)我可以如下定义一个宏

d) I can define a macro as below

   PRINTBLITZ(myvar) std::cout<<myvar<<std::endl

但是通过GDB,我无法传递宏并执行它.

but via GDB i cannot pass a macro and execute it.

我们怎样才能简单地从 GDB

How can we simply execute something like below from GDB

std::cout<<myvar<<std::endl

请为该问题提出任何解决方案. 任何建议都将受到高度赞赏,并会加快我的调试速度.

Please suggest any solution for this issue. Any suggestion is highly appreciated, and accelerate my debug.

非常感谢您!

推荐答案

  1. 我无法通过GDB的调用功能来调用模板函数-这也有帮助

实际上,在尝试了几种替代方法之后,您似乎可以这样做,但是很难正确地点上它.

Actually, after trying a few alternatives it seems that you can, but it is hard to dot it properly.

考虑以下代码

#include <iostream>

double tripleInput(double x) { return 3 * x; }

template <typename T>
inline T doubleInput(T x) {
    return 2 * x;
}


int main(int argc, char *argv[])
{
    std::cout << doubleInput(13) << std::endl;
    std::cout << doubleInput(1.72) << std::endl;

    std::cout << tripleInput(1.72) << std::endl;
    return 0;
}

使用调试符号进行编译并使用可执行文件启动gdb后,我们可以这样做

After compiling with debug symbols and starting gdb with the executable we can do

call tripleInput(1.5)

和gdb将返回4.5.到目前为止,一切都很好.但是请注意,如果您编写call tri并按TAB键,则gdb将使名称完整为tripleInput(double).之后,添加(1.5)并可以

and gdb will return 4.5. So far so good. Note however, that if you write call tri and press TAB gdb will complete the name as tripleInput(double). After that you add (1.5) and you can run as

tripleInput(double)(1.5)

它将像以前一样工作.

现在让我们尝试使用模板化的doubleInput函数.那是模板的名称,但是只有当您以某种类型使用模板时,编译器才会从模板生成函数.实际名称为doubleInput<int>doubleInput<double>等.只有您实际使用的版本 才会出现在二进制文件中,并且可以被gdb看到.

Now let's try with the templated doubleInput function. That is the name of the template, but only once you use the template with some type is that the compiler will generate a function from the template. The actual names are doubleInput<int>, doubleInput<double>, etc. Only versions you have actually used will be in the binary and can be seen by gdb.

现在让我们尝试

call doubleInput<double>(1.7)

和gdb返回3.3999999999999999.伟大的!注意

and gdb returns 3.3999999999999999. Great! Notice that

call doubleInput<double>(double)(1.7)

也可以.请注意

call doubleInput<int>(1.7)

返回2,而不是3.3999999999999999,但这很有意义.

returns 2, instead of 3.3999999999999999, but that makes sense.

因此,答案是只要传递全名(使用TAB即可完成名称),就可以调用模板的实例.

So, the answer is that you can call instances of the template, as long as you pass the full name (use TAB to complete the name).

最后一点,如果我更改了TripleInput和doubleInput以通过引用而不是通过值来接收参数,则它将无法工作,并且会出现错误尝试获取不在内存中的值的地址"

Just a final note, if I change the tripleInput and doubleInput to receive the argument by reference, instead of by value, then it won't work and I get the error "Attempt to take address of value not located in memory".

  1. 现在的问题是我正在使用许多类型的多维数组,我必须对每个数组进行重载

使用前面的答案,这意味着您可以编写单个模板而不是多个实现.只需确保调用一次即可.即使您确实实现了几个功能,也仍然需要调用它们,以使链接器不会将其从二进制文件中删除.

With the previous answer, it means that you could write a single template instead of multiple implementations. Just be sure to call it once. Even if you do implement several functions, you still need to call them such that the linker does not remove it from the binary.

但是,到目前为止,为了帮助调试最佳解决方案,正在使用gdb的Python API编写用于bliz::Array类型的自定义漂亮打印机.如果您有用于突击型打印机的漂亮打印机,而看到blitz::Array所需的就是p variable_name.即使您正在从核心文件进行调试(始终运行不下,您也无法调用函数),这始终可以正常工作.

But in order to help debugging the best solution, by far, is using gdb's Python API to write custom pretty printers for bliz::Array types. If you had pretty printers for blitz types and all you needed to see a blitz::Array was p variable_name. This would always work even if you are debugging from a core file (without an inferior running you can't call a function).

不幸的是,我找不到用于闪电战的漂亮打印机的任何现有实现,这意味着您必须自己编写.

Unfortunately, I could not find any existing implementation of pretty printers for blitz, which means that you would have to write it yourself.

我没有闪电战的经验,但是我经常使用 armadillo ,它是C ++库用于线性代数科学计算,而且我已经为犰狳类型编写了漂亮的打印机.参见此答案

I don't have experience with blitz, but I often use armadillo, which is a C++ library for linear algebra & scientific computing, and I have written pretty printers for armadillo types. See this answer and this repository if you are curious.

编写漂亮的打印机需要您对编写漂亮的打印机类型以存储其数据的方式有所了解.您需要阅读 gdb的文档,但是最好的方法是查看漂亮打印机的其他实现.至少我就是这么做的.

Writing pretty printers requires you to understand a little about the way that the type you are writing pretty printers for stores its data. You will need to read gdb's documentation about it, but the best way is to look other implementations of pretty printers. At least that's how I've done it.

这篇关于通过GDB打印闪电战阵列的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆