Как я могу проверить список STL в отладчике CodeWarrior?
Есть ли простой способ просмотра данных в STL std::list<T>
в отладчике Metrowerks CodeWarrior? Я могу просматривать данные в начале или в конце списка, просматривая такие выражения, как
instances->__list_imp.__list_deleter.end_.compressed_pair_imp.second_.prev_->data_
Я могу развернуть маленькие знаки "+" рядом с членами структуры, чтобы пройти список элементов за раз, но это утомительно, и после примерно 20-30 элементов дерево становится слишком широким для окна отладчика. Список, который я изучаю, содержит более 2000 элементов.
Отладчик CodeWarrior не поддерживает вызов функций в выражениях, поэтому я не могу проверить значение (++(++instances.begin()))
или что-то подобное. Я могу только смотреть на членов структуры, которые имеют очень длинные и неудобные имена.
Окно отладчика также ограничено примерно 245 символами, поэтому я не могу написать скрипт для генерации смехотворно длинного выражения, которое будет расширено до N-го узла.
Я пытаюсь отладить проблему, для воспроизведения которой требуется несколько часов выдержки, поэтому все, что требует постепенного добавления кода, перекомпиляции и повторной отладки, не будет очень полезным. Если нет другого выбора, тогда, возможно, мне придется это сделать.
3 ответа
Это определенно не "легкий путь" (он может быть не проще, чем то, что вы делаете с "+"), но я нахожу это более полезным, чем в некоторых случаях иметь дело с видом на часы. Это также может позволить вам выполнить отладку в действительно плохих обстоятельствах (где представление наблюдения практически не работает по какой-либо причине или когда у вас просто есть файл двоичного дампа памяти).
С std::list у вас обычно есть реализация, которая выглядит примерно так в памяти (обратитесь к за подробностями при необходимости):
список структур { Узел * следующий; Узел * пред; размер_т размер; } шаблон struct Node { Узел * следующий; // последний узел будет указывать на список, а не на другой узел Узел * пред; // первый узел будет указывать на список, а не на другой узел Т полезная нагрузка; // например, в std::list это будет полезная нагрузка Foo * }
Обратите внимание, что next и prev могут быть в обратном порядке в вашей реализации.
& myList в большинстве случаев эквивалентен end() в большинстве реализаций.
Если вы используете вид памяти, вы можете поиграть рядом с &myList. Это позволит вам найти значение указателя myList.prev или myList.next, а затем изменить представление памяти, чтобы посмотреть на это. Затем вы попали на последний или первый узел в вашем списке соответственно.
Добравшись до узла, вы можете посмотреть на prev, next или payload, а затем перейти к prev или next; вспенить, промыть, повторить. Если вы снова окажетесь в &myList, вы знаете, что вы прошли через все это.
Больно и скучно? Возможно. Но вы хорошо знакомы с вашей реализацией stl, в некоторых случаях вы можете легко "увидеть" возможные остановки, и это полезный навык, когда все другие возможности выходят за пределы окна.
(Ведите записи о том, где вы были, запутаться очень легко.)
Оказывается, проблема, с которой я столкнулся, была связана с тем фактом, что в списке было несколько тысяч элементов - в нем должно было быть всего пара десятков элементов, макс.
В этой конкретной реализации STL, prev
указатели хранились со смещением 0 каждого узла, поэтому я мог переходить по обратным ссылкам, просто многократно разыменовывая ссылки. Следующее чудовище оглядывается назад на 20 ссылок:
********************((Metrowerks::node_base**********************)instances->__list_imp.__list_deleter.end_.compressed_pair_imp.second_)
Следование прямым ссылкам еще страшнее, так как вы должны смещаться на 4 байта после каждой разыменования.
Отладчики могут быть гораздо более дружественными к STL. Я не знаком с CodeWarrior конкретно, но так ли это, что вы вообще не можете вызывать какие-либо функции из окна отладки? Или это больше похоже на другие отладчики, которые я использовал, когда вы (1) не можете вызывать функции, если программа уже завершена (ABORT, segfault, ...) и (2) не могут вызывать функции, которые включают в себя расширения шаблонов (что может потребовать добавления кода к изображению), но (3) может вызывать статически связанные функции, если код остановлен на точке останова?
В последнем случае вы можете добавить одну или несколько не шаблонных функций в ваш код, которые копируют list<T>
в массив T в стиле C, для определенных типов, которые вас интересуют. Если вы можете вызвать функцию такого типа из окна отладки, сделайте это, а затем изучите элементы массива, чтобы выяснить, что находится в вашем списке. Если вы не можете вызвать функцию из окна отладки, вам может потребоваться сделать некоторые вызовы этой функции в вашем коде близко к точке ошибки и посмотреть на результаты. Если возможно, защитите эти вызовы, чтобы они вызывались только тогда, когда у вас установлен какой-либо флаг отладки.