Установка аппаратной точки наблюдения GDB / как установить программную точку наблюдения - PullRequest
18 голосов
/ 12 августа 2010

Предыдущий вопрос объяснял, что на x86 размер наблюдаемых объектов ограничен регистрами отладки. Как и ожидалось, я могу «смотреть» двойную переменную. Но я не могу посмотреть двойной датаблок, например,

watch pObject->dPrice

производит

Hardware watchpoint 1: pObject->dPrice

Но когда вы пытаетесь продолжить выполнение, он говорит

Не удалось вставить аппаратные точки останова: Возможно, вы запросили слишком много аппаратных точек останова / наблюдения.

даже если это только точка останова / точка наблюдения.

Мне любопытно, почему это так, но что более важно, есть ли способ обойти это? Согласно документации GDB он может использовать программные точки наблюдения, если не может использовать аппаратное обеспечение. В этом случае он не пытается использовать программную точку наблюдения - есть ли способ заставить ее это сделать?

Ответы [ 3 ]

18 голосов
/ 12 августа 2010

Да, вы можете:

установить can-use-hw-watchpoints 0

С 5.1.2 Настройка точек наблюдения :

Вы можете заставить GDB использовать только программные точки наблюдения с помощью команды set can-use-hw-watchpoints 0.Если эта переменная установлена ​​в ноль, GDB никогда не будет пытаться использовать аппаратные точки наблюдения, даже если базовая система их поддерживает.(Обратите внимание, что аппаратные контрольные точки, которые были установлены до установки can-use-hw-watchpoints равными нулю, все равно будут использовать аппаратный механизм отслеживания значений выражений.)

set can-use-hw-watchpoints

Установите, использовать ли аппаратные точки наблюдения.

show can-use-hw-watchpoints

Показать текущий режим использования аппаратных точек наблюдения.

7 голосов
/ 13 августа 2010

Я не уверен на 100%, но, насколько я понимаю, когда вы смотрите pObject->dPrice, GDB пытается просмотреть все, что может изменить наблюдаемое значение.

Используя программные точки наблюдения, после каждого шага проверки GDBесли выражение изменилось.Используя аппаратные контрольные точки, GDB должен установить контрольную точку для dprice, как вы ожидаете, а также для pObject.

. Теперь вы отметили вопрос «x86».На x86 вы можете установить точки останова до четырех байтов.Двойник - это восемь байтов.Если вы хотите смотреть двойные, я думаю, что GDB потребуются две аппаратные точки наблюдения.Вам также нужна дополнительная точка наблюдения для pObject.Я предполагаю, что GDB пытается просмотреть все из pObject, что восходит к проблеме в вопросе, который вы связали в вопросе.

Когда я хочу сделать что-то подобное,если я уверен, что указатель pObject не изменится, я обычно делаю:

p &pObject->dprice

Допустим, GDB говорит, что адрес (double *) 0xabcdef10, теперь я делаю:

watch (double *) *0xabcdef10

и смотреть только то, что я хочу.

Примечание. Передо мной нет открытой GDB, поэтому у меня может быть неверный синтаксис для команды watch (относительно размещения*), поэтому сначала проверьте это.

6 голосов
/ 15 февраля 2017

Краткий ответ: используйте watch -location pObject->dPrice или краткую форму watch -l.

Длинный ответ: Цитирование руководства GDB :

Наблюдение за комплексомвыражения, которые ссылаются на многие переменные, также могут исчерпать ресурсы, доступные для аппаратных точек наблюдения.Это потому, что GDB необходимо отслеживать каждую переменную в выражении с отдельно выделенными ресурсами.

GDB буквально следит за самим выражением, а не по тому адресу, на который оно указывает.В этом случае это означает, что точка останова сработает, если само значение pObject будет изменено для указания нового dPrice;есть не только точка наблюдения для pObject->dPrice, но и точка для pObject.Это может быть больше, чем доступно.

Более подробный пример:

// Set a watchpoint on '*p' before running
#include <stdio.h>

int a = 0;
int b = 0;
int c = 0;
int* p = &a;

int main()
{
    puts("Hi"); // Dummy lines to make the results clearer, watchpoints stop at the line after the change
    *p = 1; // Breaks: *p was changed from 0 to 1
    puts("Hi");
    a = 2; // Breaks: a is *p, which changed from 1 to 2
    puts("Hi");
    p = &b; // Breaks: p is now b, changing *p from 2 to 0
    puts("Hi");
    p = &c; // Doesn't break: while p changed, *p is still 0
    puts("Hi");
    p = NULL; // Breaks: *p is now unreadable
    puts("Hi");
    return 0;
}

Теоретически это полезная функция;Вы можете наблюдать сложное выражение, ломающееся, как только оно ложное, что-то вроде постоянно проверяемого утверждения.Например, вы можете watch a==b в вышеуказанной программе.

На практике это неожиданно, часто вызывает эту проблему, и обычно это не то, что вам нужно.

Чтобы смотреть только цельадрес, используйте watch -location pObject->dPrice.(Это доступно с GDB 7.3, выпущенной в июле 2011 года; если вы используете что-то более старое, используйте print &pObject->dPrice и watch *(double*)0x12345678 или любой другой адрес, который он печатает.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...