【问题标题】:printing blitz arrays via GDB通过 GDB 打印 blitz 数组
【发布时间】:2020-05-08 07:28:30
【问题描述】:

最近几天我一直在使用 Blitz 阵列包。 在调试期间,我需要打印数组内容,并且 blitz 支持如下所示

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

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

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 调试器上,我可以简单地调用这个函数,如下所示

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

(gdb) 定义 printmyvar 调用 (void)operator

当我尝试如下打印数组时

(gdb) printmyvar blitz_array_name

我收到此错误“无法将函数运算符

d) 我可以定义如下宏

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

但通过 GDB 我无法传递宏并执行它。

我们怎样才能简单地从 GDB

执行类似下面的操作
std::cout<<myvar<<std::endl

请针对此问题提出任何解决方案。 任何建议都非常感谢,并加速我的调试。

提前非常感谢您!

【问题讨论】:

    标签: c++ arrays printing gdb


    【解决方案1】:
    1. 我无法通过 GDB 的调用功能调用模板函数 - 这也会有所帮助

    其实,在尝试了一些替代方案之后,似乎可以,但很难正确地点。

    考虑下面的代码

    #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 后,我们可以这样做

    call tripleInput(1.5)
    

    并且 gdb 将返回 4.5。到现在为止还挺好。但是请注意,如果您编写 call tri 并按 TAB,gdb 将完成名称为 tripleInput(double)。之后你添加(1.5),你可以运行为

    tripleInput(double)(1.5)
    

    这将像以前一样工作。

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

    现在让我们试试

    call doubleInput<double>(1.7)
    

    并且 gdb 返回3.3999999999999999。伟大的!请注意

    call doubleInput<double>(double)(1.7)
    

    也可以。请注意

    call doubleInput<int>(1.7)
    

    返回 2,而不是 3.3999999999999999,但这是有道理的。

    所以,答案是你可以调用模板的实例,只要你传递全名(使用TAB来完成名称)。

    最后一点,如果我将 TripleInput 和 doubleInput 更改为通过引用而不是按值接收参数,那么它将不起作用,并且我收到错误“尝试获取不在内存中的值的地址” .


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

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


    但是为了帮助调试最好的解决方案,到目前为止,是使用 gdb 的 Python API 为bliz::Array 类型编写自定义漂亮的打印机。如果你有漂亮的闪电战类型打印机,那么你只需要看到blitz::Array 就是p variable_name。即使您从核心文件进行调试,这也将始终有效(如果没有劣质运行,您将无法调用函数)。

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

    我没有使用 blitz 的经验,但我经常使用 armadillo,这是一个用于线性代数和科学计算的 C++ 库,并且我为犰狳类型编写了漂亮的打印机。如果您有兴趣,请参阅 this answerthis repository

    编写漂亮的打印机需要您对编写漂亮打印机的类型存储其数据的方式有所了解。你需要阅读gdb's documentation 来了解它,但最好的方法是查看漂亮打印机的其他实现。至少我是这样做的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-11-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-26
      • 1970-01-01
      • 2023-04-03
      相关资源
      最近更新 更多