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

发布于 2024-07-18 04:25:49 字数 613 浏览 5 评论 0原文

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

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

我可以展开结构成员旁边的小“+”符号以一次遍历列表一个元素,但这很乏味,大约之后20-30 个元素,树对于调试器窗口来说太宽了。 我正在检查的列表有 2000 多个元素。

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

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

我正在尝试调试一个需要几个小时浸泡才能重现的问题,因此任何需要增量添加代码、重新编译和重新调试的事情都不会很有帮助。 但如果没有其他选择,那么我可能不得不这样做。

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

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.

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.

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.

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

以往的大感动 2024-07-25 04:25:49

这绝对不是一个“简单的方法”(它可能并不比您使用“+”所做的更容易),但我确实发现它在某些情况下比处理监视视图更有帮助。 它还可能允许您在非常糟糕的情况下进行调试(其中监视视图由于某种原因几乎不起作用,或者您只有一个二进制内存转储文件)。

使用 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
}

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

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

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

一旦到达某个节点,您可以查看上一个、下一个或有效负载,然后转到上一个或下一个; 起泡沫,冲洗,重复。 如果您最终回到 &myList,您就知道您已经浏览了整个内容。

痛苦又无聊? 可能吧。 但是您确实对 stl 实现非常熟悉,在某些情况下您可以轻松地“看到”可能的踩踏,并且当所有其他可能性都飞出窗外时,这是一项有用的技能。

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

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):

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.

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

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.

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.

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.

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

吖咩 2024-07-25 04:25:49

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

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

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?

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.

泪冰清 2024-07-25 04:25:49

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

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

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

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

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:

********************((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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文