【问题标题】:Eclipse CDT (4.5.1) works slow with pretty printingEclipse CDT (4.5.1) 打印速度慢
【发布时间】:2016-10-14 20:26:43
【问题描述】:

我对庞大的嵌套数据结构有疑问(来自 JSON Spirit)。在调试时,当这个结构被数据填充时,Eclipse 开始工作很慢,在每一步之后它都等待来自 GDB 的打印数据。问题是即使我没有扩展这个数据结构,Eclipse 也会收集很多关于局部变量的信息。当漂亮的打印关闭时,它可以工作,但当然我在 STL 容器中看不到任何东西。

我正在使用来自GDB SVN的打印机

这里有一小段代码可以产生类似的问题:

#include <iostream>
#include <string>
#include <map>

int main() {
    std::map<std::string, std::map<std::string, std::map<std::string, std::string>>> mega_map;

    const int factor = 50;
    for (int c = 0; c < factor; ++c){
        std::map<std::string, std::map<std::string, std::string>> b_map;
        for (int b = 0; b < factor; ++b){
            std::map<std::string, std::string> a_map;
            for (int a = 0; a < factor; ++a){
                std::string a_str = "a";
                a_str += (std::to_string(a));
                auto a_pair = std::make_pair("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + a_str, "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz");
                a_map.insert(a_pair);
            }
            std::string b_str = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";
            b_str += (std::to_string(b));
            b_map[b_str] = a_map;
        }
        std::string c_str = "cccccccccccccccccccccccccccccccccccccccc";
        c_str += (std::to_string(c));
        mega_map[c_str] = b_map;
    }
    return 0;
}

只需在“返回”时刹车,您会发现在“变量”窗口中获取某些内容需要很长时间。在那段时间你不能调试。

GDB set print elements number-of-elements 中有一个标志可以限制容器中要打印的元素数量,它可以工作,但是虽然我对这些嵌套结构不感兴趣,但此设置会影响我想要检查的其他容器。

有什么解决办法吗?

谢谢。

【问题讨论】:

    标签: c++ debugging eclipse-cdt pretty-print


    【解决方案1】:

    我们(我和同事)今天遇到并调查了这个问题,这是我们的结论。不幸的是,我们没有找到仅使用某些设置来解决此问题的方法,但发现 CDT 和 GDB 中的一些更改可以帮助缓解它。如果您可以构建自己的 CDT 或 GDB,它可能会对您有所帮助。

    CDT 使用-stack-list-locals 向 GDB 询问本地人,并使用参数来获取他们的值。对于打印精美的容器,GDB 最终会包含子项:

    std::vector of length 20, capacity 20 = {<children here>}
    

    对于嵌套数据结构,它最终可能会很大。一种解决方法是让 CDT 不询问这些值。它将正确使用变量对象并在您扩展数据结构时根据需要询问值。这是差异:

    diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIStack.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIStack.java
    index c319eb8..23bbb8a 100644
    --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIStack.java
    +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIStack.java
    @@ -859,7 +859,7 @@ implements IStack, ICachingService {
                fMICommandCache.execute(
                        // Don't ask for value when we are visualizing trace data, since some
                        // data will not be there, and the command will fail
    -                   fCommandFactory.createMIStackListLocals(frameDmc, !fTraceVisualization),
    +                   fCommandFactory.createMIStackListLocals(frameDmc, false),
                        new DataRequestMonitor<MIStackListLocalsInfo>(getExecutor(), rm) {
                            @Override
                            protected void handleSuccess() {
    @@ -988,7 +988,7 @@ implements IStack, ICachingService {
                    // the result without the values
                    // Don't ask for value when we are visualizing trace data, since some
                    // data will not be there, and the command will fail
    -               fCommandFactory.createMIStackListLocals(frameDmc, !fTraceVisualization),
    +               fCommandFactory.createMIStackListLocals(frameDmc, false),
                    new DataRequestMonitor<MIStackListLocalsInfo>(getExecutor(), countingRm) {
                        @Override
                        protected void handleSuccess() {
    

    在其他情况下,CDT 会发出请求,使 GDB 吐出完整的递归数据结构,也就是说,如果您在变量视图中选择了变量或将其悬停。然后您会注意到“详细信息”部分中的完整扩展值。但是,如果您在步进时没有选择该变量,它会很快步进。

    GDB 中可能的解决方法是不让它以递归方式输出漂亮的打印数据结构。例如,这种 hack 将它们限制为一级子级:

    diff --git a/gdb/python/py-prettyprint.c b/gdb/python/py-prettyprint.c
    index 66929bf..b213699 100644
    --- a/gdb/python/py-prettyprint.c
    +++ b/gdb/python/py-prettyprint.c
    @@ -700,7 +700,7 @@ gdbpy_apply_val_pretty_printer (const struct extension_language_defn *extlang,
       /* Print the section */
       print_result = print_string_repr (printer.get (), hint.get (), stream,
                        recurse, options, language, gdbarch);
    -  if (print_result != string_repr_error)
    +  if (print_result != string_repr_error && recurse == 0)
         print_children (printer.get (), hint.get (), stream, recurse, options,
                language, print_result == string_repr_none);
    

    如果此递归限制是具有合理值的设置,则可以考虑对上游 GDB 的贡献。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-10-10
    • 2014-01-24
    • 2010-09-22
    • 2014-07-13
    • 1970-01-01
    • 2018-10-03
    • 2023-01-25
    • 1970-01-01
    相关资源
    最近更新 更多