DDD предоставляет несколько средств для исследования данных.
Чтобы увидеть значение простой переменной, поместите указатель мыши над ее именем. Спустя секунду всплывет маленькое окно (называемое подсказкой для значения), показывающее значение этой переменной. Окно исчезает, как только вы уберете указатель с имени переменной. Значение также показывается в строке состояния.
Подсказки для значений можно выключить через `Edit => Preferences => General => Automatic display of variable values as popup tips'.
Показ значений в строке состояния выключается через `Edit => Preferences => General => Automatic display of variable values in the status line'.
Эти настройки привязаны к следующим ресурсам:
Значение переменной можно также напечатать в консоли отладчика, что делает его доступным для будущих операций. Чтобы напечатать значение какой-то переменной, выберите ее, щелкнув первой кнопкой мыши на ее имени. Имя переменной будет скопировано в поле аргумента. Если теперь щелкнуть на кнопке `Print', значение напечатается в консоли отладчика. Кроме того, значение показывается в строке состояния.
Есть более быстрый вариант: вы можете просто нажать на имени переменной третью кнопку мыши и выбрать из всплывающего меню пункт `Print'.
При использовании GDB кнопка `Print' генерирует команду
print
, у которой есть еще несколько параметров. См. раздел `Examining Data' в Debugging with GDB,
о специфичных для GDB выражениях, переменных и выходных форматах.
Чтобы исследовать сложные структуры данных, вы можете отобразить их в окне данных. Окно данных отображает избранные данные вашей программы, графически изображая сложные структуры. Оно обновляется при каждом останове программы.
В этом разделе рассказывается как создавать и удалять отображения и манипулировать ими. Базовые операции:
Чтобы создать новое отображение, показывающее некую переменную, выберите эту переменную, щелкнув на ее имени первой кнопкой мыши. Имя переменной будет скопировано в поле аргумента. Если теперь щелкнуть на кнопке `Display', в окне данных появится новое отображение. Окно данных открывается автоматически, как только вы создаете отображение.
Есть более короткий способ: вы можете просто нажать на имени переменной третью кнопку мыши и выбрать из всплывающего меню пункт `Display'.
В качестве еще более быстрого способа, можно также дважды щелкнуть на имени переменной.
Еще один способ: можно ввести выражение, которое нужно отобразить, в поле аргумента и нажать кнопку `Display'.
И наконец: вы также можете набрать команду в подсказке отладчика:
graph display выражение [clustered] [at (x, y)] [dependent on отображение] [[now or] when in область]
Эта команда создает новое отображение, показывающее значение указанного выражения. Необязательные части означают следующее:
clustered
at (x, y)
dependent on отображение
when in область
now or when in область
У каждого отображения в окне данных есть заголовок, содержащий его номер и отображаемое выражение (имя отображения). Под заголовком показывается значение отображения.
Вы можете выделить отображение, щелкнув на нем первой кнопкой мыши.
Можно расширить существующее выделение, нажав во время выбора клавишу Shift. Также можно переключить существующее выделение, удерживая клавишу Shift при выборе уже выделенных отображений.
Отдельные отображения можно также выделять, используя курсорные стрелки Up, Down, Left и Right.
Для выделения нескольких отображений нажмите и удерживайте первую кнопку мыши где-нибудь на заднем плане окна. При перемещении указателя показывается прямоугольник выделения; все отображения внутри этого прямоугольника будут выделены, когда вы отпустите кнопку мыши.
Если в процессе выделения нажата клавиша Shift, существующее выделение расширяется.
Двойной щелчок на заголовке отображения автоматически выделяет это отображение и все соединенные с ним.
Составные значения (например, записи, структуры, классы и массивы) могут отображаться в развернутом виде, то есть со всеми подробностями, или скрыто, в виде `{...}'.
Чтобы увидеть подробности составной величины, выберите эту величину, щелкнув на ее имени или значении первой кнопкой мыши и нажмите кнопку `Show'. Подробности показываются как для самой составной величины, так и для содержащихся в ней подструктур.
Чтобы скрыть подробности составной величины, выберите эту величину, щелкнув на ее имени или значении первой кнопкой мыши и нажмите кнопку `Hide'.
При нажатии и удержании первой кнопки мыши на кнопке `Show/Hide' всплывает меню с другими альтернативами:
Show More ()
Show Just ()
Show All ()
Hide ()
Есть более быстрый способ: вы можете также нажать на составной величине третью кнопку мыши и выбрать нужный пункт меню.
Еще более быстрый вариант: можно дважды щелкнуть на значении первой кнопкой мыши. Если какая-то часть значения скрыта, будет показано больше подробностей; если видимо все значение целиком, двойной щелчок скрывает значение. Таким способом вы можете дважды щелкать на значении до тех пор, пока не получите нужную степень подробности.
Если скрыты все подробности отображения, то такое отображение называется выключенным; на это указывает строка `(Disabled)'.
Отображения также можно включать и выключать с помощью команды DDD, вводимой в подсказке отладчика:
graph disable display отображения...
выключает заданные отображения.
graph enable display отображения...
включает заданные отображения.
В этих командах отображения... -- это либо разделенный пробелами список номеров отображений, либо имя одного отображения. Если вы задаете отображение по имени, затрагиваются все отображения с этим именем.
Для отмены включения или выключения отображений используйте `Edit => Undo'.
Массивы, структуры и списки могут быть ориентированы горизонтально или вертикально. Чтобы изменить ориентацию отображения, выделите его, а затем щелкните на кнопке `Rotate'.
Есть более быстрый способ: вы можете нажать на массиве третью кнопку мыши и выбрать из всплывающего меню пункт `Rotate'.
Если структура или список ориентированы горизонтально, DDD автоматически не показывает имена членов. Это может быть удобно для экономии места.
Последняя выбранная ориентация используется при создании новых отображений. Если в последний раз вы повернули массив горизонтально, следующий массив будет также ориентирован горизонтально. Эти установки сохраняются через `Edit => Save Options'; они связаны с такими ресурсами:
Вы можете отобразить все локальных переменные сразу, выбрав `Data => Display Local Variables'. При использовании DBX, XDB, JDB или Perl это отобразит все локальные переменные, включая аргументы текущей функции. При использовании GDB или PYDB аргументы содержатся в отдельном отображении, которое активизируется через `Data => Display Arguments'.
Отображением, показывающим локальные переменные, можно манипулировать точно так же, как любым другим. Отдельные переменные можно выделять и получать их значения.
Вы можете создать отображение из вывода произвольной команды отладчика. Если ввести
graph display `команда`
вывод команды превращается в отображение состояния, которое обновляется при каждом останове программы.
К примеру, команда
graph display `where`
создает отображение состояния с именем `Where', которое показывает текущий след вызовов.
Если вы используете GDB, DDD предоставляет панель, где вы можете выбрать полезные отображения состояния. Нажмите `Data => Status Displays' и подберите нужное отображение из списка.
Для обновления отображений состояния при каждом останове требуется некоторое время; их лучше удалять, когда они больше не нужны.
Окно данных автоматически обновляется при каждом останове программы. Значения, которые изменились с последнего обновления, подсвечиваются.
Однако, могут быть ситуации, когда вам нужно обновить окно данных вручную. Чаще всего такое случается, когда вы изменили установки отладчика, которые могут повлиять на формат данных, и хотите, чтобы в окне данных отразились эти установки.
Вы можете обновить окно данных, выбрав `Data => Refresh Displays'.
В качестве альтернативы, вы можете нажать третью кнопку мыши на фоне окна данных и выбрать пункт `Refresh Displays'.
Ввод
graph refresh
в подсказке отладчика приводит к тому же результату.
Если вы исследуете несколько переменных одновременно, выделение для каждой из них отдельного отображения займет много места на экране. Поэтому DDD поддерживает группы. Группа объединяет несколько логических отображений данных в одно физическое отображение, сберегая экранное место.
Есть два способа создания групп:
Отображения в группе можно выделять и манипулировать ими как частями обычного отображения; в частности, вы можете показывать и скрывать подробности или получать значения по указателям. Однако, нельзя проводить связки к группированному отображению, и вы можете выбирать либо только один из них, либо все сразу.
Выключение группы называется разгруппировкой, его тоже можно делать двумя способами:
Чтобы отобразить несколько последовательных объектов одного типа (часть массива или массив динамической длины), вы можете использовать в выражениях для отображения запись `от..до'.
от и до -- это числа, которые обозначают первое и последнее выражение из тех, что следует отобразить. Таким образом,
graph display argv[0..9]
создает 10 новых отображений для `argv[0]', `argv[1]', ..., `argv[9]'. Эти отображения автоматически группируются (см. раздел 7.3.1.8 Группировка отображений), так что вы можете легко обращаться с этим набором, как с массивом.
Запись `от..до' можно также применять несколько раз. Например,
graph display 1..5 * 1..5
создает удобную маленькую таблицу умножения.
Запись `от..до' создает несколько отображений; для их создания и обновления затрачивается некоторое время. Если вы хотите отобразить только часть массива, более эффективным будет использование фрагментов массива. См. раздел 7.3.2.1 Фрагменты массива, обсуждение этой темы.
Вы можете просмотреть состояние всех отображений, выбрав `Data => Displays'. Это вызывает редактор отображений.
Редактор отображений показывает свойства каждого отображения с такими полями:
Чтобы удалить одно отображение, выделите его и нажмите кнопку `Undisp'. Или вы можете нажать на этом отображении третью кнопку мыши и выбрать пункт меню `Undisplay'.
При удалении отображения автоматически выделяются его непосредственные потомки и предки, так что вы можете легко удалить целый граф.
Чтобы удалить несколько отображений за один раз, используйте кнопку `Undisp' в редакторе отображений (вызывается через `Data => Displays'). Выберите любое число отображений и удалите их, нажав `Undisp'.
Или вы можете применить такую команду DDD:
graph undisplay отображения...
В данном случае, отображения... -- это либо разделенный пробелами список номеров отображений, либо имя одного отображения. Если вы задаете отображение по имени, затрагиваются все отображения с этим именем.
Если вы используете объединенные окна, то при удалении последнего отображения из окна данных это окно автоматически закрывается. (Вы можете изменить это через `Edit => Preferences => Data => Close data window when deleting last display'.)
Если вы удалили отображение по ошибке, используйте `Edit => Undo', чтобы снова создать его.
Наконец, вы можете также вырезать, копировать и вставлять отображения с помощью пунктов `Cut', `Copy' и `Paste' из меню `Edit'. Буфер обмена хранит команды, используемые для создания отображений; `Paste' вставляет команду в консоль отладчика. Это позволяет вам сохранять отображения для будущего использования или копировать их между разными экземплярами DDD.
Вы можете использовать следующие ресурсы для управления внешним видом отображений:
В DDD есть специальные средства для обращения с массивами.
Часто бывает нужно напечатать несколько последовательных объектов одного типа; фрагмент (секцию) массива или массив динамически определяемой длины, для которого в программе существует только указатель.
В DDD вы можете отображать фрагменты с помощью записи `от..до' (см. раздел 7.3.1.9 Создание нескольких отображений). Но это подразумевает, что вы заранее знаете значения от и до; кроме того, создавать несколько одиночных отображений неэффективно. Если вы используете GDB, у вас есть другой способ.
При использовании GDB вы можете отображать последовательные объекты, ссылаясь на непрерывную область памяти как на искусственный массив с помощью бинарного оператора `@'. Левая часть `@' должна быть первым элементом желаемого массива и самостоятельным объектом. Правая часть -- это желаемая длина массива. Результатом является значение-массив, чьи элементы принадлежат типу первого аргумента. Первый элемент -- это на самом деле левый аргумент оператора; второй элемент состоит из байт памяти, непосредственно следующих после первого, и так далее.
Вот пример. Если в программе сказано
int *array = (int *) malloc (len * sizeof (int));
вы можете напечатать содержимое array
с помощью
print array[0]@len
и отобразить его, введя команду
graph display array[0]@len
Таким образом, общий вид отображения фрагмента массива такой:
graph display массив[первый]@число-элементов
где массив -- это имя отображаемого массива, первый -- это индекс первого элемента, а число-элементов -- это число отображаемых элементов.
Левый операнд `@' должен находиться в памяти. Значения-массивы, созданные таким методом при помощи оператора `@', ведут себя в отношении индексирования так же, как любые другие массивы, а при использовании в выражениях приводятся к типу указателей.
При использовании GDB значение массива, которое повторяется 10 и более раз, отображается только один раз. Это значение показывается с добавленным постфиксом `<nx>', где n -- это число повторений. Таким образом, отображение `0x0 <30x>' обозначает массив из 30 элементов, каждый из которых равен `0x0'. Это значительно экономит экранное место, особенно в случае с однообразными массивами.
По умолчанию порог для повторяющихся элементов массива равен 10. Вы
можете изменить эго через `Edit => GDB Settings =>
Threshold for repeated print elements'. Если установить порог в
значение 0
, GDB (и DDD) будут отображать все элементы
массива по отдельности. После изменения установок GDB не забывайте
обновить окно данных с помощью `Data => Refresh Displays'.
Вы также можете настроить DDD для раздельного отображения элементов массивов:
По умолчанию DDD располагает двумерные массивы в виде таблиц, так чтобы все элементы массива были выровнены относительно друг друга.(27) Чтобы выключить это средство, снимите установку `Edit => Preferences => Data => Display Two-Dimensional Arrays as Tables'. Она связана с таким ресурсом:
Во время работы программы вы можете изменять значения любых переменных.(28)
Чтобы изменить значение переменной, введите ее имя в `()' --- например, выбрав отображение или появление переменной в исходном тексте программы. Затем щелкните на кнопке `Set'. В появившемся диалоговом окне вы можете отредактировать значение переменной; щелчок на кнопке `OK' или `Apply' применяет ваше изменение и присваивает переменной новое значение.
Чтобы изменить отображаемое значение, вы также можете выбрать пункт `Set Value' из всплывающего меню.
Если вы сделали ошибку, можно применить `Edit => Undo' и снова присвоить переменной старое значение.
Помимо отображения простых значений, DDD может визуализировать зависимости между значениями -- в особенности указатели и другие ссылки, которые составляют сложные структуры данных.
Зависимые отображения создаются из существующего отображения. Зависимость обозначается связкой, ведущей от начального отображения к зависимому.
Чтобы создать зависимое отображение, выделите начальное отображение или его часть и введите в поле аргумента `():' зависимое выражение. Затем щелкните на кнопке `Display'.
Используя зависимые отображения, вы можете исследовать структуру, например, дерева, и расположить его в соответствии с вашим интуитивным пониманием дерева как структуры данных.
По умолчанию DDD не распознает разделяемые структуры данных (то есть объект, на который ссылаются несколько других объектов). См. раздел 7.3.4.3 Разделяемые структуры, для получения подробной информации о том, как исследовать такие структуры.
Есть специальные средства для создания зависимых отображений, показывающих значение, на которое ссылается указатель. Это позволяет быстро исследовать структуры данных, основанные на указателях.
Чтобы получить значение по указателю, выделите значение или имя начального указателя и щелкните на кнопке `Disp *'. Появится новое отображение, показывающее значение по этому указателю.
Более быстрый способ: вы можете нажать на значении или имени начального указателя третью кнопку мыши и выбрать пункт меню `Display *'.
Есть еще более быстрый вариант: дважды щелкните первой кнопкой мыши на значении или имени начального указателя. Есть во время двойного щелчка вы нажмете Ctrl, отображение будет заменено на значение, хранящееся по этому указателю.
Функция `Display *()' также доступна по нажатию и удержанию кнопки `Display'.
По умолчанию DDD не распознает разделяемые структуры данных -- то есть объект, на который ссылаются несколько других объектов. Например, если два указателя `p1' и `p2' ссылаются на один и тот же объект `d', отображения `d', `*p1' и `*p2' будут различными, хотя они и обозначают один и тот же объект.
DDD предоставляет специальный режим, в котором такие ситуации детектируются. DDD замечает, когда два или более отображения расположены по одному физическому адресу, и если это так, объединяет все эти псевдонимы в одно отображение, оригинальное отображение данных. Этот режим называется режимом детектирования псевдонимов; включается через `Data => Detect Aliases'.
Когда включено детектирование псевдонимов, DDD проверяет адреса всех отображений после каждого шага программы. Если два отображения имеют одинаковый адрес, они объединяются в одно. Точнее, остается только одно, которое не изменялось дольше (это оригинальное отображение данных); все остальные псевдонимы подавляются, то есть полностью скрываются. Ведущие к псевдонимам связки заменяются на связки, ведущие к оригинальному отображению.
При детектировании псевдонимов создаются особенные связки: вместо того, чтобы непосредственно соединять два отображения, они проходят через подсказку, которая описывает данную дугу.
В каждой подсказке связки есть место для скрытого псевдонима; выделение подсказки эквивалентно выделению этого псевдонима. Таким образом, вы можете легко удалять отображения-псевдонимы, просто выделяя подсказку и нажимая `Undisp'.
Для получения доступа к отображениям-псевдонимам, вы также можете использовать редкатор отображений. Скрытые отображения перечисляются в нем как псевдонимы оригинального отображения. С помощью редактора отображений можно выделять, изменять и удалять скрытые отображения.
Скрытые отображения снова становятся видимыми, как только вы выключаете детектирование псевдонимом, или если их адреса меняются так, что они больше не являются псевдонимами, или если удаляется оригинальное отображение, -- и тогда оригинальным отображением становится псевдоним, изменявшийся позднее других.
Пожалуйста, обратите внимание на следующие возможные проблемы, связанные с детектированием псевдонимов:
Детектирование псевдонимов управляется следующими ресурсами:
В DDD есть быстрое меню часто используемых выражений для работы с отображениями. Это меню активизируется нажатием и удержанием кнопки `Display', или нажатием на некотором отображении третьей кнопки мыши и выбором `New Display', или щелчком на отображении третьей кнопки мыши при нажатой клавише Shift.
Пункт быстрого меню `Other' позволяет создавать новое отображение, которое расширяет быстрое меню.
В качестве примера предположим, что вы выделили отображение с именем `date_ptr'. Если выбрать `Display => Other', появится диалоговое окно, позволяющее ввести новое отображаемое выражение -- к примеру, вы можете преобразовать отображение `date_ptr' в новое отображение `(char *)date_ptr'. Если был активизирован переключатель `Include in `New Display' Menu', быстрое меню теперь будет включать новый пункт `Display (char *)()', который преобразует любое выделенное отображение отображение в `(char *)отображение'. Такие быстрые операции могут сэкономить много времени при исследовании сложных структур данных.
Вы можете отредактировать содержимое меню `New Display', выбрав его пункт `Edit Menu'. Появится редактор быстрых операций, содержащий все быстрые выражения, которые вы можете отредактировать по своему усмотрению. Каждая строка содержит выражение для ровно одного пункта меню. Если щелкнуть на `Apply', в соответствии с этим текстом будет заново создано меню `New Display'. Если текст пуст, меню `New Display' тоже будет пустым.
DDD также позволяет задавать отдельные метки для определенных пользователем кнопок. Вы можете записать такую метку после выражения, отделив ее знаками `//'. Эта возможность используется по умолчанию в меню `New Display' для GDB, где у каждого преобразования есть своя метка:
/t () // Convert to Bin /d () // Convert to Dec /x () // Convert to Hex /o () // Convert to Oct
Если хотите, можете добавить свои преобразования. DDD поддерживает до двадцати пунктов в меню `New Display'.
Быстрое меню контролируется следующими ресурсами:
Если строка содержит разделитель метки(29), то строка до разделителя используется в качестве выражения, а строка после разделителя --- в качестве метки. Иначе, меткой будет `Display выражение'. При вызове строка `()' в выражении заменяется на имя текущего выделенного отображения.
Если у вас одновременно есть несколько отображений, вы можете организовать их по своему вкусу. В этом разделе рассказывается как это сделать.
Время от времени бывает нужно переместить отображение на другое место в окне данных. Вы можете переместить одно отображение, нажимая и удерживая на его заголовке первую кнопку мыши. Перемещая указатель при удержании кнопки, вы перемещаете все выделенные отображения.
Подсказки связок можно выделять и перемещать точно так же, как отображения. Если дуга проходит через подсказку связки, вы можете изменить форму этой дуги, передвигая подсказку.
Для точного перемещения выделенных отображений можно также воспользоваться курсорными стрелками. При нажатой клавише Shift курсорные стрелки перемещают по одному пикселю, а при нажатом Ctrl --- по узлам сетки.
Если окно данных становится слишком маленьким, и все отображения в нем не умещаются, создаются полоски прокрутки. Если DDD у вас настроен на использование панели прокрутки, то в нижнем правом углу создается панель прокрутки. Когда вы перемещаете панель прокрутки, соответственно перемещается видимая часть окна.
Чтобы перейти от полосок прокрутки к панели прокрутки, используйте `Edit => Startup => Data Scrolling' и выберите либо `Panner', либо `Scrollbars'.
Эта установка привязана к следующему ресурсу:
См. раздел 2.1.2 Ключи DDD, о ключах --scrolled-graph-editor
и
--panned-graph-editor
.
Вы можете выровнять все отображения по ближайшим узлам сетки, выбрав `Data => Align on Grid'. Это бывает полезно, если вы хотите, чтобы все связки были строго горизонтальны или вертикальны.
Если установить `Edit => Preferences => Data => Auto-align Displays on Nearest Grid Point', отображения выравниваются автоматически. Когда эта установка включена, отображения можно перемещать только по сетке.
Вы можете скомпоновать весь граф как дерево, выбрав `Data => Layout Graph'.
Компоновка графа может создать подсказки связок; то есть связки становятся не прямыми линиями, а ведут к подсказке, а от нее уже к месту назначения. Подсказки отображений можно перемещать так же, как любые отображения.
Чтобы включить более компактную компоновку, можно установить `Edit => Preferences => Data => Compact Layout'. Эта установка реализует альтернативный алгоритм компоновки, где потомки помещаются рядом со своими предками. Этот алгоритм подходит только для гомогенных структур.
Вы можете включить принудительную компоновку, выставив `Edit => Preferences => Data => Automatic Layout'. Если задействована автоматическая компоновка, граф компонуется после каждого изменения.
Вы можете повернуть весь граф на 90 градусов по часовой стрелке, выбрав `Data => Rotate Graph'.
Если граф ранее был скомпонован, может понадобиться перекомпоновать его. Последующие компоновки будут учитывать направление последнего поворота.
DDD позволяет распечатывать граф на PostScript-принтерах или в файлы. Это полезно для документирования состояний программы.
Чтобы напечатать граф на PostScript-принтере, выберите `File => Print Graph'. Введите в поле `Print Command' команду печати. Чтобы начать печать, нажмите кнопку `OK' или `Apply'.
Еще можно распечатать граф в файл. Щелкните на кнопке `File' и введите в поле `File Name' имя файла. Чтобы создать файл, щелкните на кнопке `Print'.
Когда граф печатается в файл, возможны два формата:
xfig
или для преобразования в другие форматы (в том
числе в @acronym{IBMGL}, TeX, @acronym{PIC}) с помощью программ
transfig
или fig2dev
.
Пожалуйста, обратите внимание на следующие возможные проблемы, связанные с печатью графов:
Эти установки связаны с такими ресурсами:
В этом разделе обсуждается, как DDD на самом деле создает отображения из данных.
Все данные, отображаемые в окне данных DDD, предоставляются подчиненным отладчиком. GDB, к примеру, предоставляет список отображений, содержащий символьные выражения, которые следует вычисляют т печатать на стандартный вывод при каждом останове программы. Команда GDB `display tree' добавляет к списку отображений `tree' и заставляет GDB печатать значение `tree', например, в виде `tree = (Tree *)0x20e98', при каждом останове программы. DDD обрабатывает этот вывод GDB и показывает его в окне данных.
Каждый элемент списка отображений, в том виде, в каком он передается от подчиненного отладчика, считывается в DDD и переводится в бокс. Боксы -- это такие прямоугольники с определенным содержимым, которые можно отображать в окне данных. Различают атомарные и составные боксы. Атомарный бокс содержит белый или черный пробел, линию или строку. Составные боксы -- это горизонтальные или вертикальные группы других боксов. Каждый бокс обладает размером и протяженностью, которые определяют его положение во внешнем пространстве.
Составляя все большие и большие боксы DDD создает из структуры данных GDB узел графа, подобно тому, как системы набора текстов вроде TeX строят из букв слова, а из абзацев страницы.
Такие конструкции легко выражаются посредством функций, задающих зависимость бокса от других боксов. Эти функции отображения могут задаваться пользователем, а потом интерпретироваться в DDD, с помощью функционального языка VSL, что означает visual structure language. Пользователь может сам задавать VSL-функции, это оставляет большие пространство для расширений и настроек. VSL-функция отображения, которая помещает вокруг своего аргумента рамку, выглядит так:
// Поместить рамку вокруг текста TEXT frame(text) = hrule() | vrule() & text & vrule() | hrule();
Здесь hrule()
и vrule()
-- это примитивы, возвращающие,
соответственно, горизонтальную и вертикальную линии. Операторы `&'
и `|' создают горизонтальное и вертикальное выравнивание своих
аргументов.
VSL предоставляет базовые средства, такие как сопоставление с
образцом и функции с переменным числом аргументов. Функция
halign()
, к примеру, строит горизонтальное выравнивание для
произвольного числа аргументов, которым соответствуют три точки
(`...'):
// Горизонтальное выравнивание halign(x) = x; halign(x, ...) = x & halign(...);
Часто используемые функции, вроде halign()
, собраны в стандартную
библиотеку VSL.
Чтобы визуализировать структуры данных, каждому атомарному типу и каждому типу-конструктору языка программирования присваивается VSL-функция отображения. Атомарные значения, такие как числа, знаки, перечисления или строки, отображаются с помощью строковых боксов, содержащих их значение; VSL-функция для их отображения оставляет их без изменений:
// Атомарные значения simple_value(value) = value;
Составные значения требуют большего внимания. Массив, к примеру, можно отобразить при помощи горизонтального выравнивания:
// Массив array(...) = frame(halign(...));
Когда GDB посылает DDD значение массива, вызывается VSL-функция `array()' с элементами этого массива в качестве значений. Таким образом, выражение-массив GDB `{1, 2, 3}' вычисляется в VSL как
array(simple_value("1"), simple_value("2"), simple_value("3"))
что эквивалентно
"1" & "2" & "3"
составному боксу, содержащему три горизонтально выровненных строковых бокса. VSL-функция, которая используется в DDD на самом деле, также помещает между элементами разделители, и у нее есть вертикальный вариант.
Вложенные структуры, вроде многомерных массивов, отображаются путем
последовательного применения функции array()
внизу вверх.
Сначала array()
применяется к наиболее глубоко вложенным
структурам; затем результирующие боксы передаются в качестве аргументов
в еще один вызов array()
. Вывод GDB
{{"A", "B", "C"}, {"D", "E", "F"}}
представляющий массив строк размером 2 на 3, вычисляется в VSL как
array(array("A", "B", "C"), array("A", "B", "C"))
результатом чего является выровненный горизонтальный бокс двух других боксов, представляющих внутренние массивы.
Структуры-записи строятся похожим способом, с использованием функции
отображения struct_member
,
для отрисовки членов записи. Имена и значения разделяются знаком
равенства:
// Член структуры-записи struct_member (name, value) = name & " = " & value;
Функция отображения struct
рисует саму запись с помощью функции
valign()
.(30)
// Структура-запись struct(...) = frame(valign(...));
Это простой пример; VSL-функция, которая на самом деле используется в DDD, еще пытается выровнять знаки равенства; кроме того, она гарантирует, что применяются разделители для правильного языка, что свернутые структуры отрисовываются правильно, и так далее.
С DDD поставляется встроенная библиотека VSL, которой должно быть достаточно для большинства, если не для всех, нужд. Используя следующие ресурсы можно изменять и улучшать определения VSL:
Общий шаблон для замены определения функции функция на новое определение нов_опр такой:
#pragma replace функция function(аргументы...) = нов_опр;
Часто используются такие VSL-функции:
color(бокс, цвет-текста [, цвет-фона])
display_color(бокс)
title_color(бокс)
disabled_color(бокс)
simple_color(бокс)
pointer_color(бокс)
struct_color(бокс)
array_color(бокс)
reference_color(бокс)
changed_color(бокс)
stdfontfamily()
stdfontsize()
0
(по умолчанию) говорит, что
следует применять `stdfontpoints()'.
stdfontpoints()
0
говорит, что следует
применять `stdfontsize()'. По умолчанию 90
.
stdfontweight()
Чтобы установить цвет указателей в значение "red4", напишите
Ddd*vslDefs: \ #pragma replace pointer_color\n\ pointer_color(box) = color(box, "red4");\n
Чтобы установить размер шрифта равным 10.0 пунктов, используйте
Ddd*vslDefs: \ #pragma replace stdfontsize\n\ #pragma replace stdfontpoints\n\ stdfontsize() = 0;\n stdfontpoints() = 100;\n
Чтобы по умолчанию использовался 12-пиксельный шрифт courier, напишите
Ddd*vslDefs: \ #pragma replace stdfontsize\n\ #pragma replace stdfontfamily\n\ stdfontsize() = 12;\n\ stdfontfamily() = family_courier();\n
Другие определения, которые вы можете перекрыть с помощью ресурса `vslDefs', смотрите в файле `ddd.vsl'.
Если дистрибутив исходников DDD у вас установлен в `/opt/src', вы можете использовать следующие установки, чтобы библиотека VSL считывалась из `/home/joe/ddd.vsl':
Ddd*vslLibrary: /home/joe/ddd.vsl Ddd*vslPath: .:/opt/src/ddd/ddd:/opt/src/ddd/vsllib
Включаемые VSL-файлы, на которые ссылается `/home/joe/ddd.vsl', сначала ищутся в текущем каталоге `.', потом в `/opt/src/ddd/ddd/', а потом в `/opt/src/ddd/vsllib/'.
Вместо того чтобы предоставлять еще одну библиотеку VSL, часто бывает проще задать какие-то незначительные изменения для встроенной библиотеки. Подробности смотрите выше, в описании ресурса `vslDefs'.
Если вам нужно исследовать огромный объем числовых данных, рисунок часто может сказать больше, чем тысяча чисел. Поэтому DDD позволяет вам рисовать числовые значения в виде двух- и трехмерных графиков.
DDD может строить графики двух типов числовых значений:
Чтобы построить график массива фиксированного размера, выделите его имя, щелкнув на нем первой кнопкой мыши. Имя массива будет скопировано в поле аргумента. Если щелкнуть на кнопке `Plot', в окне данных появится новое отображение, а потом будет создано новое окно верхнего уровня, содержащее график значений.
Для построения графика массива динамического размера вы должны использовать фрагмент массива (см. раздел 7.3.2.1 Фрагменты массива). Введите в поле аргумента
массив[первый]@число-элементов
где массив -- это имя отображаемого массива, первый -- это индекс первого элемента, а число-элементов -- это число отображаемых элементов. Затем щелкните на `Plot', чтобы начать построение графика.
Также вы можете получить график значений введя в подсказке отладчика такую команду:
graph plot выражение
Она работает подобно `graph display выражение' (и принимает такие же аргументы; см. раздел 7.3.1.1 Создание единичных отображений), но еще дополнительно показывает значение в окне графика.
Каждый раз, когда во время выполнения программы значение изменяется, график обновляется по текущим значениям. Окно графика остается активным до тех пор, пока вы не закроете его (через `File => Close'), или пока не будет удалено соответствующее ему отображение.
На самом деле DDD не сам строит график. Вместо этого он полагается
на внешнюю программу gnuplot
.
DDD добавляет к окну графика Gnuplot полоску меню, которая позволяет вам изменять внешний вид графика:
При просмотре трехмерного графика можно менять точку наблюдения с помощью полосок прокрутки. Горизонтальная полоска прокрутки поворачивает график вокруг оси z, то есть вправо или влево. Вертикальная полоска прокрутки поворачивает вокруг оси y, то есть вверх или вниз.
Вы также можете, если хотите, изменять размер окна графика.
Кроме графиков массивов, DDD может также строить графики скаляров (простых числовых величин). Делается это так же, как для массивов --- вы выбираете числовую переменную, щелкаете на `Plot', и появляется график. Однако, построение графика скаляра не так интересно. График, не содержащий ничего кроме скаляра, просто отображает значение этого скаляра в виде константы y -- то есть горизонтальную прямую.
Тогда зачем вообще беспокоиться о скалярах? DDD позволяет объединять на одном графике несколько значений. Основная идея такова: если вы хотите построить график чего-то, что не является ни массивом, ни скаляром, DDD берет из этого чего-то все числовые значения, какие может найти и чертит их графики в одном окне. Например, вы можете построить график всех локальных переменных, выбрав `Data => Display Local Variables' и нажав затем `Plot'. При этом создается график, содержащий все числовые переменные, найденные среди локальных переменных. Аналогично, вы можете получить график всех числовых членов какой-то структуры, выбрав ее и нажав `Plot'.
Если вы хотите точнее контролировать, что включать в график, а что нет, вы можете применить группы отображений (см. раздел 7.3.1.8 Группировка отображений). Довольно часто строят график одномерного массива вместе с текущим индексом. Это делается в три этапа:
Отображаемые вместе в массивами скаляры могут отрисовываться в виде либо горизонтальных, либо вертикальных линий. По умолчанию скаляры рисуются в виде горизонтальных линий. Однако, если скаляр является индексом ранее начерченного массива, он показывается как вертикальная линия. Вы можете изменить первоначальную ориентацию, выделив отображение скаляра и нажав `Rotate'.
При каждом останове программы DDD записывает значения всех отображаемых переменных, чтобы вы могли "отменить" выполнение программы (см. раздел 6.8 "Отмена" выполнения программы). Для таких историй отображений тоже можно построить график. Пункт меню `Plot => Plot history of ()' создает график, в котором показаны все записанные ранее значения выделенного отображения.
Если вы хотите распечатать график, выберите `File => Print Plot'. Появится диалог для печати графиков. Так же, как для графов, у вас есть выбор между печатью на принтере или в файл, и вы можете установить нужные параметры.
Собственно печать производит опять же Gnuplot, используя подходящий драйвер. Пожалуйста, обратите внимание на следующие возможные проблемы, связанные с печатью:
С помощью `File => Command' можно вводить команды Gnuplot напрямую. Каждая введенная в подсказку `gnuplot>' команда пересылается в Gnuplot, а после нее выдается команда `replot', которая обновляет изображение. Это полезно для выполнения в Gnuplot более сложных задач.
Вот простой пример. Команда Gnuplot
set xrange [xmin:xmax]
устанавливает диапазон отображения по горизонтали в значение xmin...xmax. Чтобы построить график только элементов от 10 до 20, введите:
gnuplot> set xrange [10:20]
После ввода каждой команды DDD добавляет команду replot
,
поэтому график обновляется автоматически.
А вот более сложный пример. Следующая последовательность команд Gnuplot сохраняет график в формате TeX:
gnuplot> set output "plot.tex" # Устанавливает имя выходного файла gnuplot> set term latex # Задает выходной формат gnuplot> set term x11 # Снова показывает первоначальное изображение
Из-за неявной команды replot
вывод автоматически записывается
в файл `plot.tex' после команды set term latex
.
Диалоговое окно запоминает введенные команды; чтобы восстановить ранее введенное, используйте курсорные стрелки. Сообщения об ошибках от Gnuplot (если они были), также показываются в области истории.
Диалог между DDD и Gnuplot сохраняется в файле
`~/.ddd/log' см. раздел 10.12.1 Запись протокола). Ключ DDD
--trace
печатает этот диалог на стандартный вывод.
Если вы хотите обработать данные графика с помощью какой-то внешней
программы (отдельной программой Gnuplot или программой xmgr
,
например), вы можете записать данные графика в файл, используя
`File => Save Data As'. При этом появится диалоговое окно,
позволяющее выбрать файл, в котором будут сохранены данные.
Генерируемый файл начинается несколькими строками комментариев. Затем идут сами данные в формате X/Y или X/Y/Z. Это тот же самый файл, какой обрабатывает Gnuplot.
Если вы хотите увидеть, как ваши данные меняются с течением времени, вы
можете создать точку останова, последовательность команд которой
завершается командой cont
(см. раздел 5.1.8 Команды точек останова).
Каждый раз, когда достигается эта точка останова "с продолжением",
DDD обновляет отображаемые значения, в том числе и графики. Затем
DDD выполняет последовательность команд точки останова, продолжая
выполнение.
Таким способом вы можете установить точку останова с "продолжением" в каком-то характерном месте внутри обрабатывающего массив алгоритма, и DDD будет отображать процесс графически. Когда ваша программа остановится на самом деле, вы можете применить `Undo' и `Redo', чтобы снова отобразить и исследовать предыдущие ее состояния. См. раздел 6.8 "Отмена" выполнения программы, для дополнительной информации.
Вы можете указать, как вызывается программа Gnuplot, и настроить некоторые базовые установки.
С помощью `Edit => Preferences => Helpers => Plot' вы можете указать, как вызывается программа Gnuplot. Это привязано к такому ресурсу:
С помощью `Edit => Preferences => Helpers => Plot Window' вы можете указать, следует ли использовать для графика окно Gnuplot (`External') или окно DDD (`builtin'). Это привязано к такому ресурсу:
mwm
, плохо справляются с
методами поглощения.
Можно и дальше управлять взаимодействием с внешним окном графика:
2000
.
Чтобы изменить установки Gnuplot, используйте такие ресурсы:
set parametric set urange [0:1] set vrange [0:1] set trange [0:1]
Установка `parametric' необходима, чтобы Gnuplot понимал генерируемые DDD файлы данных. Команды, задающие диапазоны, используются для построения графиков скаляров.
Дополнительные команды смотрите в документации по Gnuplot.
При использовании GDB или DBX вы можете просматривать содержимое памяти в нескольких форматах, независимо от типов данных вашей программы. Пункт меню `Data => Memory' выводит панель, где вы можете выбрать нужный формат.
В этой панели вы можете ввести
Есть два способа исследования значений: