Просмотр массива в LLDB: эквивалент оператора GDB '@' в Xcode 4.1 - PullRequest
70 голосов
/ 15 августа 2011

Я хотел бы просмотреть массив элементов, на которые указывает указатель. В GDB это можно сделать, обработав указанную память как искусственный массив заданной длины, используя оператор '@' как

*pointer @ length

где length - количество элементов, которые я хочу просмотреть.

Приведенный выше синтаксис не работает в LLDB, поставляемом с Xcode 4.1.

Есть ли способ, как выполнить вышесказанное в LLDB?

Ответы [ 8 ]

116 голосов
/ 10 октября 2014

На самом деле есть простой способ сделать это, приведя указатель к указателю на массив.

Например, если у вас есть int* ptr, и вы хотите просмотреть его как массив из десяти целых чисел, вы можете сделать

p *(int(*)[10])ptr

Поскольку этот метод основан только на стандартных функциях C, этот метод работает без каких-либо плагинов или специальных настроек. Он также работает с другими отладчиками, такими как GDB или CDB, хотя они также имеют специализированные синтаксисы для печати массивов.

28 голосов
/ 16 августа 2016

Начиная с lldb в Xcode 8.0, есть новая встроенная команда parray.Таким образом, вы можете сказать:

(lldb) parray <COUNT> <EXPRESSION>

, чтобы напечатать память, на которую указывает результат EXPRESSION, в виде массива COUNT элементов типа, на который указывает выражение.

Если счет хранится в переменной, доступной в текущем кадре, помните, что вы можете сделать:

(lldb) parray `count_variable` pointer_to_malloced_array

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

26 голосов
/ 01 июля 2012

Единственный способ, который я нашел, был через скрипт-модуль Python:

""" File: parray.py """
import lldb
import shlex

def parray(debugger, command, result, dict):
    args = shlex.split(command)
    va = lldb.frame.FindVariable(args[0])
    for i in range(0, int(args[1])):
        print va.GetChildAtIndex(i, 0, 1)

Определите команду "parray" в lldb:

(lldb) command script import /path/to/parray.py
(lldb) command script add --function parray.parray parray

Теперь вы можете использовать «parray переменной длины »:

(lldb) parray a 5
(double) *a = 0
(double) [1] = 0
(double) [2] = 1.14468
(double) [3] = 2.28936
(double) [4] = 3.43404
15 голосов
/ 18 октября 2012

С Xcode 4.5.1 (который может или не может помочь вам сейчас), вы можете сделать это в консоли lldb:

(lldb) type summary add -s "${var[0-63]}" "float *"
(lldb) frame variable pointer
  (float *) pointer = 0x000000010ba92950 [0.0,1.0,2.0,3.0, ... ,63.0]

В этом примере предполагается, что указатель представляет собой массив из 64 чисел с плавающей запятой: float pointer[64];

12 голосов
/ 22 ноября 2012

Начиная с ответа Martin R, я улучшил его следующим образом:

  1. Если указатель не является простой переменной, например ::

    struct {
      int* at;
      size_t size;
    } a;
    

    Тогда «parray a.at 5» завершается неудачей.

    Я исправил это, заменив «FindVariable» на «GetValueForVariablePath».

  2. А что если элементы в вашем массиве являются агрегатами, например ::

    struct {
      struct { float x; float y; }* at;
      size_t size;
    } a;
    

    Затем "parray a.at 5" печатает: a.at-> x, a.at-> y, a.at [2], a.at [3], a.at [4], потому что GetChildAtIndex ( ) возвращает элементы агрегатов.

    Я исправил это, разрешив "a.at" + "[" + str (i) + "]" внутри цикла вместо того, чтобы разрешать "a.at" и затем извлекать его дочерние элементы.

  3. Добавлен необязательный аргумент «first» (Использование: parray [FIRST] COUNT), который полезен, когда у вас огромное количество элементов.

  4. Сделано это сделать "командный скрипт add -f parray.parray parray" в init

Вот моя модифицированная версия:

import lldb
import shlex

def parray(debugger, command, result, dict):
  args = shlex.split(command)
  if len(args) == 2:
    count = int(args[1])
    indices = range(count)
  elif len(args) == 3:
    first = int(args[1]), count = int(args[2])
    indices = range(first, first + count)
  else:
    print 'Usage: parray ARRAY [FIRST] COUNT'
    return
  for i in indices:
    print lldb.frame.GetValueForVariablePath(args[0] + "[" + str(i) + "]")

def __lldb_init_module(debugger, internal_dict):
  debugger.HandleCommand('command script add -f parray.parray parray')
12 голосов
/ 21 августа 2011

Похоже, он пока не поддерживается.

Вы можете использовать функцию чтения из памяти (чтение из памяти / x), например

(lldb) memory read -ff -c10 `test`

, чтобы десять раз напечатать число с плавающей запятойэтот указатель.Это должна быть та же функциональность, что и у GDB @.

4 голосов
/ 21 мая 2014

Я пытался добавить комментарий, но он не был хорош для публикации полного ответа, поэтому я сделал свой собственный ответ.Это решает проблему с получением «Нет значения».Вам нужно получить текущий кадр, так как я считаю, что lldb.frame установлен во время импорта модуля, поэтому у него нет текущего кадра, когда вы останавливаетесь на точке останова, если вы загружаете модуль из .lldbinit.Другая версия будет работать, если вы импортируете или перезагрузите скрипт, когда остановились на точке останова.Версия ниже всегда должна работать.

import lldb
import shlex

@lldb.command('parray', 'command script add -f parray.parray parray')
def parray(debugger, command, result, dict):

    target = debugger.GetSelectedTarget()
    process = target.GetProcess()
    thread = process.GetSelectedThread()
    frame = thread.GetSelectedFrame()

    args = shlex.split(command)
    if len(args) == 2:
        count = int(args[1])
        indices = range(count)
    elif len(args) == 3:
        first = int(args[1])
        count = int(args[2])
        indices = range(first, first + count)
    else:
        print 'Usage: parray ARRAY [FIRST] COUNT'
        return

    for i in indices:
        print frame.GetValueForVariablePath(args[0] + "[" + str(i) + "]")
1 голос
/ 17 июня 2013

Итак, вы можете написать свою собственную C-функцию и вызвать ее с помощью:

call (int)myprint(args)
...