Eclipse CDT(4.5.1)在漂亮打印时运行缓慢

时间:2016-06-14 08:06:10

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

我遇到了大量嵌套数据结构的问题(来自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;
}

只要在“返回”时踩刹车,你就会发现需要花费大量时间才能获得变量&#39;变量&#39;窗口。在此期间,您无法进行调试。

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

任何想法如何解决?

感谢。

1 个答案:

答案 0 :(得分:1)

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

CDT向GDB询问使用-stack-list-locals的本地人,并使用参数获取他们的值。对于漂亮的印刷容器,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中可能的修复方法是不要以递归方式输出漂亮的打印数据结构。例如,这种黑客将他们限制在一个级别的孩子身上:

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的贡献,此递归限制是具有可合理值的设置。