Обычно, enum
Значения являются простыми значениями, увеличиваемыми компилятором, или задаются непосредственно в виде целочисленного литерала, поэтому значения можно легко определить или увидеть непосредственно, посмотрев на исходный файл.
Однако иногда enum
значения используются для установки константы в классе, равной значению, определенному в другом месте, или результату выражения времени компиляции, которое нелегко дублировать.
Есть ли способ заставить Windbg показать мне реальную стоимость каждого enum
член для тех хитрых дел?
Рассмотрим эту небольшую структуру:
struct foo
{
enum enum1
{
enum1_val1_ = 5,
enum1_val2_,
};
enum enum2
{
enum2_val1_ = 0x0001,
enum2_val2_ = 0x0010,
};
enum
{
// assume these come from complicated compile-time expressions
some_class_constant_ = 86,
another_one_ = 99,
};
};
Самый быстрый способ — это использовать dt
команда, используя переключатели -r
(Рекурс, который вам нужно перечислить enum
члены) и -v
(многословный, который вам нужно перечислить enum
ы вообще):
0:000> dt -r -v foo
LangTestingD!foo
struct foo, 3 elements, 0x1 bytes
Enum enum1, 2 total enums
enum1_val1_ = 0n5
enum1_val2_ = 0n6
Enum enum2, 2 total enums
enum2_val1_ = 0n1
enum2_val2_ = 0n16
Enum <unnamed-tag>, 2 total enums
some_class_constant_ = 0n86
another_one_ = 0n99
Вы можете видеть, что в нем перечислены значения каждого перечисления, даже неназванного. Несколько неназванных перечислений будут перечислены правильно.
Проблема с dt -r -v foo
является то, что он перечисляет каждого члена foo
: все члены данных, все члены функции, все перечисления, а также он пытается войти в каждый и перечисляет его члены. Если foo
это сложный класс, который довольно легко получить с помощью наследования, результат будет огромным, и будет трудно найти то одно перечисление, которое вы ищете.
Так что следующий вариант заключается в том, чтобы сказать dt
какое перечисление вы хотите, а именно:
0:000> dt foo::enum1
LangTestingD!foo::enum1
enum1_val1_ = 0n5
enum1_val2_ = 0n6
Хорошо, отлично! Но как насчет этого неназванного enum? Ну, вы говорите, проверьте вывод выше, где он использует <unnamed-tag>
, Может быть, мы можем использовать это.
0:000> dt foo::<unnamed-tag>
Couldn't resolve error at 'foo::<unnamed-tag>'
Это на самом деле будет работать, но вам нужно использовать пару дополнительных переключателей. Когда вы объединяете -n
(следующий параметр является именем) и -y
(сопоставьте следующий параметр как префикс имени), тогда он, вроде, работает:
0:000> dt -n -y foo::<unnamed-tag>
LangTestingD!foo::<unnamed-tag>
some_class_constant_ = 0n86
Однако в списке указано только первое значение. Еще хуже, если есть несколько неназванных перечислений, только первое значение первого перечислено. Часто этого бывает достаточно, так как несколько неназванных перечислений не слишком распространены, но если они вам абсолютно необходимы, вам придется использовать -r -v
и просто найти их в выводе.
Других решений пока нет …