如何检查CodeWarrior调试器中的STL列表?

时间:2021-02-09 20:22:41

Is there any easy way to view the data in an STL std::list<T> in the Metrowerks CodeWarrior debugger? I can view data near the beginning or end of the list by looking at expressions such as

有没有简单的方法来查看Metrowerks CodeWarrior调试器中的STL std :: list 中的数据?我可以通过查看表达式来查看列表开头或结尾附近的数据

instances->__list_imp.__list_deleter.end_.compressed_pair_imp.second_.prev_->data_

I can expand the little '+' signs next to the struct members to walk the list an element at a time, but this is tedious, and after about 20-30 elements, the tree gets too wide for the debugger window. The list I'm examining has over 2000 elements.

我可以扩展struct成员旁边的小'+'符号,一次一行地遍历列表,但这很繁琐,在大约20-30个元素之后,树对于调试器窗口来说太宽了。我正在检查的清单有2000多个元素。

The CodeWarrior debugger does not support calling functions in expressions, so I can't examine the value of (++(++instances.begin())) or somesuch. I can only look at struct members, which have very long and inconvenient names.

CodeWarrior调试器不支持在表达式中调用函数,因此我无法检查(++(++ instances.begin()))或其中的某些值。我只能看看结构成员,它们名称很长且不方便。

The debugger window is also limited to about 245 characters, so I can't write a script to generate a ridiculously long expression that will expand to the Nth node.

调试器窗口也限制在大约245个字符,因此我无法编写脚本来生成一个可扩展到第N个节点的可笑长表达式。

I'm trying to debug a problem that requires several hours of soaking to reproduce, so anything that requires adding code incrementally, recompiling, and redebugging will not be very helpful. If there's no other option, though, then I may have to do that.

我正在尝试调试需要几个小时浸泡才能重现的问题,因此任何需要逐步添加代码,重新编译和重新调整的内容都不会非常有用。但是,如果没有其他选择,那么我可能必须这样做。

3 个解决方案

#1


This definitely isn't an "easy way" (it may not be easier than what you're doing with "+"), but I do find it more helpful than dealing with the watch view in some cases. It also may allow you to debug in really bad circumstances (where the watch view is nearly non-functional for whatever reason, or where you just have a binary memory dump file).

这肯定不是一个“简单的方法”(它可能不比你用“+”做的更容易),但我觉得它比在某些情况下处理手表视图更有帮助。它还可以允许您在非常糟糕的情况下进行调试(无论出于何种原因,监视视图几乎不起作用,或者您只有二进制内存转储文件)。

With a std::list, you typically have an implementation that looks something like this in memory (consult <list> for specifics if necessary):

使用std :: list,您通常在内存中有一个类似于此的实现(如果需要,请参阅 以获取详细信息):

struct List
{
  Node * next;
  Node * prev;
  size_t size;
}

template 
struct Node
{
  Node * next;  // last node will point to list rather than another node
  Node * prev;  // first node will point to list rather than another node
  T payload; // e.g. in a std::list this would be a Foo * payload
}

Note that next and prev may be in the opposite order in your implementation.

请注意,next和prev可能与您的实现中的顺序相反。

&myList is basically equivalent to "end()" in most implementations.

&myList在大多数实现中基本上等同于“end()”。

If you use memory view, you can poke around near &myList. This will let you find the value of the myList.prev or myList.next pointer, then change memory view to look at that. You've then gotten to the last or first node in your list, respectively.

如果您使用内存视图,则可以在&myList附近查看。这将让你找到myList.prev或myList.next指针的值,然后更改内存视图以查看它。然后,您分别到达列表中的最后一个或第一个节点。

Once you get to a node, you can look at prev, next, or payload, then go to prev or next; lather, rinse, repeat. If you end up back at &myList, you know you've traversed the whole thing.

到达节点后,您可以查看prev,next或payload,然后转到prev或next;泡沫,冲洗,重复。如果你最终回到&myList,你知道你已经遍历了整个事情。

Painful and boring? Possibly. But you do get a lot of familiarity with your stl implementation, you can "see" possible stomps easily in some cases, and it's a useful skill to have when all other possibilities fly out the window.

痛苦无聊?有可能。但是你确实对你的stl实现有了很多熟悉,在某些情况下你可以“看到”可能的轻松,当所有其他可能性飞出窗外时,它是一个有用的技能。

(Keep notes of where you've been, it's really easy to get confused.)

(记下你去过的地方,很容易混淆。)

#2


Debuggers could certainly be a lot more STL-friendly. I'm not familiar with CodeWarrior specifically, but is it the case that you can't call any functions at all from the debug window? Or is it more like other debuggers I have used, where you (1) can't call functions if the program has already terminated (ABORT, segfault, ...), and (2) can't call functions that involve template expansions (which might need to add code to the image), but (3) can call statically-linked functions if the code is stopped at a breakpoint?

调试器当然可以更加友好STL。我不熟悉CodeWarrior,但是你不能从调试窗口调用任何函数吗?或者它更像我使用过的其他调试器,如果程序已经终止(ABORT,segfault,...),则(1)无法调用函数,(2)无法调用涉及模板扩展的函数(可能需要向图像添加代码),但如果代码在断点处停止,(3)可以调用静态链接的函数?

In the latter case, you might want to add one or more non-templated functions to your code that copy a list<T> into a C-style array of T, for the specific types you are interested in. If you can call that kind of function from your debug window, do that, and then examine the array elements to find out what's in your list. If you can't call the function from the debug window, you may need to put some calls to that function in your code close to the point of error, and look at the results. If possible, guard those calls so they only get called when you have some debug flag set.

在后一种情况下,您可能希望将一个或多个非模板化函数添加到代码中,将列表 复制到C样式的T数组中,以获取您感兴趣的特定类型。如果可以调用它调试窗口中的一种函数,执行此操作,然后检查数组元素以找出列表中的内容。如果无法从调试窗口调用该函数,则可能需要在代码中对该函数进行一些调用,使其接近错误点,并查看结果。如果可能,请保护这些调用,以便在设置了某些调试标志时调用它们。

#3


It turns out the problem I was having was due to the very fact that the list had several thousand elements -- it should only have had a couple dozen elements, max.

事实证明我遇到的问题是由于这个列表有几千个元素 - 它应该只有几十个元素,最多。

In this particular STL implementation, the prev pointers were stored at offset 0 of each node, so I could follow back links by just repeatedly dereferencing. The following monstrosity looks backwards 20 links:

在这个特定的STL实现中,prev指针存储在每个节点的偏移0处,因此我可以通过重复解除引用来跟踪链接。以下怪物向后看20个链接:

********************((Metrowerks::node_base**********************)instances->__list_imp.__list_deleter.end_.compressed_pair_imp.second_)

Following forward links is even uglier, since you have to offset by 4 bytes after each dereference.

跟随前向链接甚至更加丑陋,因为每次取消引用后你必须偏移4个字节。

#1


This definitely isn't an "easy way" (it may not be easier than what you're doing with "+"), but I do find it more helpful than dealing with the watch view in some cases. It also may allow you to debug in really bad circumstances (where the watch view is nearly non-functional for whatever reason, or where you just have a binary memory dump file).

这肯定不是一个“简单的方法”(它可能不比你用“+”做的更容易),但我觉得它比在某些情况下处理手表视图更有帮助。它还可以允许您在非常糟糕的情况下进行调试(无论出于何种原因,监视视图几乎不起作用,或者您只有二进制内存转储文件)。

With a std::list, you typically have an implementation that looks something like this in memory (consult <list> for specifics if necessary):

使用std :: list,您通常在内存中有一个类似于此的实现(如果需要,请参阅 以获取详细信息):

struct List
{
  Node * next;
  Node * prev;
  size_t size;
}

template 
struct Node
{
  Node * next;  // last node will point to list rather than another node
  Node * prev;  // first node will point to list rather than another node
  T payload; // e.g. in a std::list this would be a Foo * payload
}

Note that next and prev may be in the opposite order in your implementation.

请注意,next和prev可能与您的实现中的顺序相反。

&myList is basically equivalent to "end()" in most implementations.

&myList在大多数实现中基本上等同于“end()”。

If you use memory view, you can poke around near &myList. This will let you find the value of the myList.prev or myList.next pointer, then change memory view to look at that. You've then gotten to the last or first node in your list, respectively.

如果您使用内存视图,则可以在&myList附近查看。这将让你找到myList.prev或myList.next指针的值,然后更改内存视图以查看它。然后,您分别到达列表中的最后一个或第一个节点。

Once you get to a node, you can look at prev, next, or payload, then go to prev or next; lather, rinse, repeat. If you end up back at &myList, you know you've traversed the whole thing.

到达节点后,您可以查看prev,next或payload,然后转到prev或next;泡沫,冲洗,重复。如果你最终回到&myList,你知道你已经遍历了整个事情。

Painful and boring? Possibly. But you do get a lot of familiarity with your stl implementation, you can "see" possible stomps easily in some cases, and it's a useful skill to have when all other possibilities fly out the window.

痛苦无聊?有可能。但是你确实对你的stl实现有了很多熟悉,在某些情况下你可以“看到”可能的轻松,当所有其他可能性飞出窗外时,它是一个有用的技能。

(Keep notes of where you've been, it's really easy to get confused.)

(记下你去过的地方,很容易混淆。)

#2


Debuggers could certainly be a lot more STL-friendly. I'm not familiar with CodeWarrior specifically, but is it the case that you can't call any functions at all from the debug window? Or is it more like other debuggers I have used, where you (1) can't call functions if the program has already terminated (ABORT, segfault, ...), and (2) can't call functions that involve template expansions (which might need to add code to the image), but (3) can call statically-linked functions if the code is stopped at a breakpoint?

调试器当然可以更加友好STL。我不熟悉CodeWarrior,但是你不能从调试窗口调用任何函数吗?或者它更像我使用过的其他调试器,如果程序已经终止(ABORT,segfault,...),则(1)无法调用函数,(2)无法调用涉及模板扩展的函数(可能需要向图像添加代码),但如果代码在断点处停止,(3)可以调用静态链接的函数?

In the latter case, you might want to add one or more non-templated functions to your code that copy a list<T> into a C-style array of T, for the specific types you are interested in. If you can call that kind of function from your debug window, do that, and then examine the array elements to find out what's in your list. If you can't call the function from the debug window, you may need to put some calls to that function in your code close to the point of error, and look at the results. If possible, guard those calls so they only get called when you have some debug flag set.

在后一种情况下,您可能希望将一个或多个非模板化函数添加到代码中,将列表 复制到C样式的T数组中,以获取您感兴趣的特定类型。如果可以调用它调试窗口中的一种函数,执行此操作,然后检查数组元素以找出列表中的内容。如果无法从调试窗口调用该函数,则可能需要在代码中对该函数进行一些调用,使其接近错误点,并查看结果。如果可能,请保护这些调用,以便在设置了某些调试标志时调用它们。

#3


It turns out the problem I was having was due to the very fact that the list had several thousand elements -- it should only have had a couple dozen elements, max.

事实证明我遇到的问题是由于这个列表有几千个元素 - 它应该只有几十个元素,最多。

In this particular STL implementation, the prev pointers were stored at offset 0 of each node, so I could follow back links by just repeatedly dereferencing. The following monstrosity looks backwards 20 links:

在这个特定的STL实现中,prev指针存储在每个节点的偏移0处,因此我可以通过重复解除引用来跟踪链接。以下怪物向后看20个链接:

********************((Metrowerks::node_base**********************)instances->__list_imp.__list_deleter.end_.compressed_pair_imp.second_)

Following forward links is even uglier, since you have to offset by 4 bytes after each dereference.

跟随前向链接甚至更加丑陋,因为每次取消引用后你必须偏移4个字节。