В стеке вызовов, что это указывает, когда аргумент указателя типа содержит адрес шаблона 0x8080808080808080 или 0xf8f8f8f8f8f8f8f8? - PullRequest
0 голосов
/ 11 сентября 2018

Когда я отлаживал проблему с помощью GDB, я столкнулся с этим странным поведением. За что я не смог убедить себя ни одним логическим ответом.

Ниже приведен снимок стека вызовов, полученный из-за точки останова в начале функции (для простоты я ограничиваю фрейм стека до 3 уровня).

(gdb) 
#0  hashset_get (hashset=<value optimized out>, item_key=0x7fffd7e4f5b8)
    at /xxx/yyy/zzz/hashset.c:123
#1  0x00007fffed855d00 in hashmap_get (hashmap=<value optimized out>, key=0x7fffd7e4f648)
    at /xxx/yyy/zzz/hashmap.c:789
#2  0x00007ffa589d8eeb in hashmap_get_value (hashmap=0x7ff9d82d1b78, key=0x7fffd7e4f648)
    at /xxx/yyy/zzz/hashmap.c:456

После этого выполняется одношаговое выполнение. Позже, какой кадр стека выглядел как ниже-

    (gdb) bt
#0  hashset_get (hashset=0xf8f8f8f8f8f8f8f8, item_key=0x7fffd7e4f5b8)
    at /xxx/yyy/zzz/hashset.c:125
#1  0x00007fffed855d00 in hashmap_get (hashmap=<value optimized out>, key=0x7fffd7e4f648)
    at /xxx/yyy/zzz/hashmap.c:789
#2  0x00007ffa589d8eeb in hashmap_get_value (hashmap=0x7ff9d82d1b78, key=0x7fffd7e4f648)
    at /xxx/yyy/zzz/hashmap.c:456

Я знаю, что когда GDB показывает любую переменную как " значение, оптимизированное из ", это указывает, что ее значение сохраняется в регистре, а не сохраняется в кадре стека.

Однако, в этом случае arg hashset, который первоначально отображался как " значение, оптимизированное из ", позже изменяется на некоторое местоположение адреса - 0xf8f8f8f8f8f8f8f8. Значит ли это, что изначально он сохранил hashset в регистре, а затем создал пробел в кадре стека?

И этот адрес не похож ни на какой другой адрес ячейки памяти. Вы можете увидеть какой-то шаблон в адресе (например, f8f8 ...)

Чтобы еще больше сбить с толку тот факт, что, если я попытаюсь распечатать данные в этом месте, GDB выведет, как показано ниже -

(gdb) p *hashset
Cannot access memory at address 0xf8f8f8f8f8f8f8f8

Я попробовал еще кое-что, надеясь, что это поможет понять это поведение.

Я назначил действительный адрес 0x7fffd7e4f5b8 - который хранится в аргументе item_key, hashset

(gdb) s hashset=0x7fffd7e4f5b8
(gdb) p *hashset
Cannot access memory at address 0xb8b8b8b8b8b8b8b8
(gdb) p hashset
$6 = (hashset) 0xb8b8b8b8b8b8b8b8

Но, к моему удивлению, когда я печатаю значение hashset, адрес отображается как 0xb8b8b8b8b8b8b8b8 вместо 0x7fffd7e4f5b8 !!

Может кто-нибудь объяснить, что здесь происходит?

[Редактировать: НЕТ сбоя / зависания. Система в рабочем состоянии, обычно]

1 Ответ

0 голосов
/ 13 сентября 2018

Я знаю, что когда GDB показывает любую переменную как «оптимизированное значение», это означает, что ее значение сохраняется в регистре, а не хранится в кадре стека.

То есть'то, что означает "оптимизированное значение".

Это означает: компилятор не предоставил информацию о местоположении для этой переменной в текущем программном счетчике.

Теоретически, DWARF стандартдостаточно богат, чтобы он мог описывать такие вещи, как «эту переменную можно найти, добавив constant к значению register» или «добавив register A и register B и ИЛИ результат с contents of location pointed by register C».На практике, немногие компиляторы идут на такую ​​длину, и вместо этого просто опускают информацию.

Однако в этом случае хэш-набор arg, который первоначально показывался как «оптимизированное значение», позже изменяется на некоторыйадрес местоположения

Когда вы добавили счетчик программ, GDB обнаружил информацию о местоположении на новом ПК.Но интерпретация этой информации о местоположении привела к значению 0xf8f8f8f8f8f8f8f8, которое не может быть истинным значением указателя на x86_64.

Из этого можно сделать вывод, что либо информация о местоположенииневерно (ошибка компилятора; скорее всего) или из-за того, что GDB неправильно интерпретировал описание DWARF (не неслыханно).

К сожалению, такие артефакты отладки являются реальностью при отладке оптимизированного кода.Они также зависят от точных версий GCC и GDB - более новые версии часто (но не всегда!) Лучше.Clang / LLVM в настоящее время довольно беден и производит «оптимизированную стоимость» гораздо чаще, чем следовало бы.

...