Как просмотреть член структуры для каждой переменной структуры, которая имеет этот тип? - PullRequest
3 голосов
/ 05 апреля 2011

Я получаю искажение члена структуры, где структура используется для создания большое дерево. Я пытаюсь установить точку наблюдения, но «переменная» имеет различные имена (все примеры, которые я видел, используют явные глобальные переменные, так что не показывайте примеры того, что я ищу).

(gdb) watch *(OP*)->op.sibling
A syntax error in expression, near `->op.sibling'.
(gdb) watch *(struct op*)->op.sibling
A syntax error in expression, near `->op.sibling'.
(gdb) watch (struct op*)->op.sibling
A syntax error in expression, near `->op.sibling'.

ближе всего к приемлемому синтаксису не работает

(gdb) watch (struct op*)o->op.sibling
No symbol "o" in current context.

Есть ли какая-то форма выражения, которую я пропускаю, которая была бы независимой имени переменной и обратите внимание на тот факт, что ее вид структуры?

Сможет ли это обнаружить перезапись memset структуры? (даже если нет, это помогло бы мне исключить некоторые причины)

Есть ли ссылка на GDB, которая выходит за рамки базового использования? (для некоторых определений 'basic')

Ответы [ 2 ]

13 голосов
/ 06 апреля 2011

Как говорит ниндзя, вам нужен адрес для просмотра; В этом весь смысл наблюдения. Рассмотрим следующий пример:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

typedef struct node {
  long value;
  struct node *next;
} node;

node *build_node(int x, node *next)
{
  node *n = malloc(sizeof(*n));
  n->value = x;
  n->next = next;
  return n;
}

int main()
{
  node *n = build_node(1, NULL);
  n = build_node(2, n);
  n = build_node(3, n);

  memset(&n->next->value, 0xFF, sizeof(long) + 3);  // corrupt the list

  return 0;
}

Здесь я генерирую список целых чисел, затем искажаю его. Давайте посмотрим, как это выглядит в GDB:

gdb -q ./a.out
Reading symbols for shared libraries .. done
(gdb) b main
Breakpoint 1 at 0x100000e0c: file foo.c, line 20.
(gdb) r
Starting program: /tmp/a.out 
Reading symbols for shared libraries +. done

Breakpoint 1, main () at foo.c:20
20    node *n = build_node(1, NULL);

(gdb) b 26
Breakpoint 2 at 0x100000e8d: file foo.c, line 26.
(gdb) c
Continuing.

Breakpoint 2, main () at foo.c:26
26    return 0;
(gdb) p *n
$1 = {
  value = 3, 
  next = 0x100100090
}
(gdb) p *n.next
$2 = {
  value = -1, 
  next = 0x100ffffff
}

Здесь мы ясно видим, что n->next полностью испорчено. Предположим, что мы не знали, где это происходит, и хотели узнать об этом через точку наблюдения GDB.

Сначала нам нужно установить адрес, который был поврежден:

(gdb) print &n.next.value
$3 = (long int *) 0x100100090
(gdb) watch *$3
Hardware watchpoint 3: *$3

Здесь я просто установил точку наблюдения по адресу 0x100100090 на 8 байтов.

(gdb) run
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /private/tmp/a.out 
warning: Could not set watchpoint 3
warning: Could not set watchpoint 3

Breakpoint 1, main () at foo.c:20
20    node *n = build_node(1, NULL);

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

(gdb) enable 3
(gdb) c
Continuing.
Hardware watchpoint 3: *$3

Old value = 0
New value = 2
build_node (x=2, next=0x100100080) at foo.c:14
14    n->next = next;

Хорошо, мы достигли ожидаемой точки и ожидаемого значения. Следующая модификация испортит его, и мы хотим знать, где это происходит.

(gdb) c
Continuing.
Hardware watchpoint 3: *$3

Old value = 2
New value = 255
0x00007fff82fae450 in memset ()
(gdb) bt
#0  0x00007fff82fae450 in memset ()
#1  0x0000000100000ebe in __inline_memset_chk (__dest=0x100100090, __val=255, __len=11) at _string.h:80
#2  0x0000000100000e8d in main () at foo.c:24

Вуаля, теперь ты знаешь, откуда взялась неожиданная модификация.

1 голос
/ 05 апреля 2011

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

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