как получить адрес объекта std :: vector в lldb / Xcode

У меня есть стек, выделенный std::vector это переписывается неким мошенническим кодом. Это не данные перезаписывается, но внутреннее состояние. Я знаю это, потому что size() Функция-член возвращает нежелательное значение некоторое время в программу. Инициализируется правильно. Я подозреваю общую ошибку указателя в другом месте в моем коде.

я использую Xcode 4.6.2. Я хочу установить аппаратную точку останова (с lldb) при доступе к памяти первой ячейки памяти вектора (самого вектора, а не данных), чтобы я мог видеть, что его перезаписывает. В соответствии с этот Мне нужно сначала найти адрес вектора. Обычно можно использовать & оператор, чтобы получить адрес переменной, но по какой-то причине с lldb это не возвращает адрес, а вместо этого выводит какую-то итоговую строку.

class myClass {
public:
myClass() : myVector(4) {}
private:
std::vector<double> myVector;
double myDouble;
};

После разрыва в произвольной точке останова после того, как все построено:

(lldb) frame variable &myObject.myVector
(std::vector<double, std::allocator<double> > *) $7 = size=4

‘expr’ имеет тот же результат:

(lldb) expr &myObject.myVector;
(std::vector<double, std::allocator<double> > *) $8 = size=4

Обычно я ожидаю увидеть напечатанный адрес, например, с этим простым элементом данных:

(lldb) frame variable &myObject.myDouble
(double *) &myDouble = 0x0000000125589328

Я попытался присвоить адрес переменной с помощью ‘expr’, но это тоже не работает:

(lldb) expr std::vector<double, std::allocator<double> > * f = &myObject.myVector; f
(std::vector<double, std::allocator<double> > *) $12 = size=0

Возвращенный там нулевой размер (вместо 4) предполагает, что он все равно не выбрал правильный вектор.

Итак, как мне получить адрес этого вектора? Если я щелкну на нем правой кнопкой мыши в списке переменных кадра Xcode и выберу «Просмотр памяти» этого вектора, то откроется вид 0x0 что, конечно, неверно. Обратите внимание, что вектор расположен в стеке — он фактически находится внутри нескольких других объектов, но все они построены из стека.

Обратите внимание, что я не желая получить адрес данных в векторе — на самом деле это не перезаписывается. Это внутреннее хранилище выделенного стека векторного объекта, которое повреждено.

3

Решение

Ваш myObject Объект, скорее всего, является локальной переменной и существует в стеке:

(lldb) p &myObject
(myClass *) $0 = 0x00007fff5fbffad8
(lldb) p $fp >= &myObject && &myObject >= $sp
(bool) $1 = true

Если вы хотите, чтобы lldb не печатал вектор красиво, используйте -R / --raw-output возможность frame variable:

(lldb) fr va -R myObject
(myClass) myObject = {
myVector = {
std::_Vector_base<double, std::allocator<double> > = {
_M_impl = {
_M_start = 0x00000001001008d0
_M_finish = 0x00000001001008f0
_M_end_of_storage = 0x00000001001008f0
}
}
}
myDouble = 6.95322297580907e-310
}

Вы заметите, что адреса на векторе — это куча адресов, то есть они были malloc‘ed (new‘, что угодно) вместо того, чтобы находиться внутри вашего myObject непосредственно. Так что теперь вы должны решить, что вы хотите контролировать. Если вы хотите отслеживать вектор, чтобы увидеть, как новый элемент добавляется в конец вашего вектора, то вы хотите наблюдать указатель конца вектора,

(lldb) p &myObject.myVector._M_impl._M_finish
(double **) $4 = 0x00007fff5fbffae0

Если вы хотите контролировать содержимое одного из векторов, скажем первый, то вы хотите контролировать

(lldb) p myObject.myVector._M_impl._M_start
(double *) $6 = 0x00000001001008d0

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

Обычно форматеры типа lldb (для std::vector в этом случае) предпочтительнее, чем просмотр необработанной реализации, но если вы хотите работать с необработанной реализацией, в этом случае может быть проще отключить средства форматирования. например

(lldb) type category disable  gnu-libstdc++
(lldb) p myObject
(myClass) $9 = {
(std::vector<double, std::allocator<double> >) myVector = {
(std::_Vector_base<double, std::allocator<double> >) std::_Vector_base<double, std::allocator<double> > = {
(std::_Vector_base<double, std::allocator<double> >::_Vector_impl) _M_impl = {
(double *) _M_start = 0x00000001001008d0
(double *) _M_finish = 0x00000001001008f0
(double *) _M_end_of_storage = 0x00000001001008f0
}
}
}
(double) myDouble = 6.95322297580907e-310
}

Вы можете увидеть все встроенные в lldb средства форматирования типов с помощью type summary list команда.

8

Другие решения

Как дополнение, вы должны были сказать:
(lldb) выражение набора точек наблюдения &myVector
даже если вы не можете «увидеть» значение

Кроме того, вы увидели сводку для std :: vector — получается, что мы не указывали, чтобы сводка либо не применялась к указателям, ни для отображения значения.

Я исправил LLDB с открытым исходным кодом, который позволит вам увидеть числовое значение указателя.
Возможно, действительно правильным решением будет специальный сводный формат для указателей, который показывает ценность & резюме. Тем не менее, я не слишком рад этому пути, поскольку он дублировал бы количество форматеров регулярных выражений, которые мы имеем в LLDB, что, возможно, не лучшее решение для повышения производительности.

1

По вопросам рекламы [email protected]