【问题标题】:gdb Could not find operator[]gdb 找不到运算符 []
【发布时间】:2014-07-30 13:44:42
【问题描述】:
double var1, var2;
std::vector<double *> x;

var1 = 1;
var2 = 2;

x.push_back(&var1);
x.push_back(&var2);

当我在 gdb 中调试此代码并尝试 print x[0]*x[0] 时,我得到:

找不到运算符[]。

现在,如果我在 push_back 之后加入这一行:

x[0] = &var1;

我可以访问 gdb 中的任何特定元素。其他成员也会发生同样的事情,例如front()at() 等。我的理解是编译器/链接器仅包含源代码中存在的成员函数,而那些是我可以在 gdb 中使用的成员函数。有没有办法包含std::vector 的每个成员函数,以便我可以在 gdb 中访问它们?

【问题讨论】:

  • 关闭优化?
  • 我不确定如何阻止编译器/链接器从可执行文件中剥离 [] 运算符代码,但请查看此答案以了解潜在的解决方法:stackoverflow.com/questions/253099/…
  • @Qix 我只有 -g -Wall on
  • 它没有被“剥离”,因为它从未添加。据我回忆(是的,它很粗略;你知道的星期一),该运算符不是虚拟的,如果没有使用,也不会扩展给定类型的实现。但是,您可能可以明确地强制它,尽管我承认从未尝试过。
  • 这能回答你的问题吗? Forcing the compiler to generate code for all member functions of a template class? {请注意,每个问题中都有一些未包含在另一个问题中的答案。}

标签: c++ vector gdb


【解决方案1】:

我的理解是编译器/链接器只包括源代码中存在的成员函数,而那些是我可以在 gdb 中使用的。

您的理解不正确/不完整。

std::vector 是一个模板类。如果没有显式实例化,编译器需要实例化调用的方法(通常是源中存在的方法的子集)。

有没有办法包含 std::vector 的每个成员函数,以便我可以在 gdb 中访问它们?

对于给定类型T,您应该能够通过请求显式实例化该T整个向量,例如:

template class std::vector<double>;

【讨论】:

  • +1,我不知道显式实例化完全实例化了作品。在你提到它之前,从来没有真正想过它。现在我想得更多,这完全有道理。谢谢你今天教我一些东西!。
  • 为什么显式实例化必须放在主函数之外?
  • @duleshi 显式实例化过程生成一个可识别的类,相当于定义一个类。如果你不能在 main 中定义一个类,我不明白为什么你应该被允许在 main 中进行显式实例化。
  • 我用过这个,效果很好,谢谢!!但我不明白为什么我必须这样做,因为在我的代码中我确实使用了模板类的operator[](即boost::interprocess::offset_ptr,顺便说一句)所以我猜它无论如何都必须被实例化。而且我使用优化。
  • 只是一个评论。在 Ubuntu 16 LTS 上,这些显式实例化是不必要的,但在 Mac 上它们。我不能说我试图关闭所有可能的编译器优化(我只是遵守了没有像 O1、O2 或 O3 这样的额外技巧)。 @Employed Russian 帮助我结束了三个小时痛苦的反复试验。
【解决方案2】:

尝试按向量的内部成员打印。

print *(x._M_impl._M_start+0)

这里0 是您要检查的数据的索引。

灵感来自this answer

【讨论】:

    【解决方案3】:

    或者,您可以使用下面的 GDB 扩展,它会戳 GNU libstdc++ 的 std::vector 字段,因此无论 operator[] 是否被实例化都可以工作。

    加载:

    (gdb) guile (load "the-file.scm")
    

    这会创建一个新的vref 命令:

    (gdb) vref my_vector 0
    

    代码(需要使用 Guile 支持构建的 GDB):

    (use-modules (gdb)
                 (ice-9 match))
    
    (define (std::vector-ref vector index)
      (let* ((impl  (value-field vector "_M_impl"))
             (start (value-field impl "_M_start")))
        (value-subscript start index)))
    
    (define %vector-ref-command
      (make-command "vref"
                    #:command-class COMMAND_OBSCURE
                    #:doc "Access an element of an std::vector."
                    #:invoke
                    (lambda (self args tty?)
                      (match (string-tokenize args)
                        ((variable index)
                         (let* ((value (std::vector-ref (parse-and-eval variable)
                                                       (string->number index)))
                                (index (history-append! value)))
                           (format #t "$~a = ~a~%"
                                   index (value-print value)))))
                      #t)))
    
    (register-command! %vector-ref-command)
    

    【讨论】:

      【解决方案4】:

      .at()、.begin() 函数出于某种原因对我有用。可能是因为我设置了 -g 标志。

      【讨论】:

      • edit 将其改写为更自信的答案。因为这篇文章有可能被误认为是一个问题,这在此处是不合适的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-10
      • 2015-07-15
      • 2021-06-08
      • 2013-12-04
      • 1970-01-01
      相关资源
      最近更新 更多