我遇到了大量嵌套数据结构的问题(来自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
中有一个标志可以限制要打印的容器中的元素数量,它可以工作但是我对这些嵌套结构不感兴趣,这个设置会影响我想要检查的其他容器。
任何想法如何解决?
感谢。
答案 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的贡献,此递归限制是具有可合理值的设置。