Ich möchte ein Array von Elementen anzeigen, auf die ein Zeiger zeigt. In GDB kann dies durch Behandeln des spitzen Speichers als künstliches Array einer bestimmten Länge unter Verwendung des Operators '@' als erfolgen
*pointer @ length
Wo length
ist die Anzahl der Elemente, die ich anzeigen möchte?
Die obige Syntax funktioniert nicht in LLDB, die mit Xcode 4.1 geliefert wird.
Gibt es eine Möglichkeit, dies in LLDB zu erreichen?
Antworten:
In lldb gibt es zwei Möglichkeiten, dies zu tun.
Am häufigsten verwenden Sie den
parray
Befehl lldb, der aCOUNT
und an akzeptiertEXPRESSION
.EXPRESSION
wird ausgewertet und sollte zu einem Zeiger auf den Speicher führen. lldb druckt dannCOUNT
Elemente dieses Typs an diese Adresse. z.Bwo
ptr
ist vom Typint *
.Alternativ kann dies durch Umwandeln des Zeigers auf einen Zeiger auf ein Array erfolgen.
Wenn Sie beispielsweise eine
int* ptr
haben und diese als Array mit zehn Ganzzahlen anzeigen möchten, können Sie dies tunp *(int(*)[10])ptr
Da diese Methode nur auf Standard-C-Funktionen basiert, funktioniert sie ohne Plugins oder spezielle Einstellungen. Es funktioniert ebenfalls mit anderen Debuggern wie GDB oder CDB, obwohl sie auch spezielle Syntaxen zum Drucken von Arrays haben.
quelle
right click on data pointer > View value as... > Custom Type...
In Ausdrucksfeld setzen*(double(*)[10])value_type
. Dadurch werden die 10 angegebenen Werte ausgedruckt. Sie können double und 10 so ändern, dass sie dem gewünschten Typ / der gewünschten Menge entsprechen.Beginnend mit der lldb in Xcode 8.0 gibt es einen neuen integrierten Parray-Befehl. Sie können also sagen:
(lldb) parray <COUNT> <EXPRESSION>
Drucken des Speichers, auf den das Ergebnis von zeigt,
EXPRESSION
als Array vonCOUNT
Elementen des Typs, auf den der Ausdruck zeigt.Wenn die Anzahl in einer Variablen gespeichert ist, die im aktuellen Frame verfügbar ist, können Sie Folgendes tun:
(lldb) parray `count_variable` pointer_to_malloced_array
Dies ist eine allgemeine lldb-Funktion. Jedes Befehlszeilenargument in lldb, das von Backticks umgeben ist, wird als Ausdruck ausgewertet, der eine Ganzzahl zurückgibt. Anschließend wird das Argument vor der Befehlsausführung durch die Ganzzahl ersetzt.
quelle
command alias
eine Verknüpfung erstellen .Der einzige Weg, den ich gefunden habe, war über ein Python-Skriptmodul:
""" 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)
Definieren Sie einen Befehl "parray" in lldb:
(lldb) command script import /path/to/parray.py (lldb) command script add --function parray.parray parray
Jetzt können Sie "parray variable length " verwenden:
(lldb) parray a 5 (double) *a = 0 (double) [1] = 0 (double) [2] = 1.14468 (double) [3] = 2.28936 (double) [4] = 3.43404
quelle
AttributeError: 'NoneType' object has no attribute 'FindVariable'
Mit Xcode 4.5.1 (was Ihnen jetzt vielleicht hilft oder nicht) können Sie dies in der lldb-Konsole tun:
(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]
In diesem Beispiel wird davon ausgegangen, dass 'Zeiger' ein Array von 64 Floats ist:
float pointer[64];
quelle
Beginnend mit der Antwort von Martin R habe ich es wie folgt verbessert:
Wenn der Zeiger keine einfache Variable ist, z.
struct { int* at; size_t size; } a;
Dann schlägt "parray a.at 5" fehl.
Ich habe dies behoben, indem ich "FindVariable" durch "GetValueForVariablePath" ersetzt habe.
Was ist nun, wenn die Elemente in Ihrem Array Aggregate sind, z.
struct { struct { float x; float y; }* at; size_t size; } a;
Dann druckt "parray a.at 5": a.at-> x, a.at-> y, a.at [2], a.at [3], a.at [4], da GetChildAtIndex () Mitglieder zurückgibt von Aggregaten.
Ich habe dies behoben, indem ich "a.at" + "[" + str (i) + "]" innerhalb der Schleife aufgelöst habe, anstatt "a.at" aufzulösen und dann seine untergeordneten Elemente abzurufen.
Es wurde ein optionales "erstes" Argument hinzugefügt (Verwendung: parray [FIRST] COUNT), das nützlich ist, wenn Sie eine große Anzahl von Elementen haben.
Hat das "Befehlsskript add -f parray.parray parray" bei init ausgeführt
Hier ist meine modifizierte Version:
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')
quelle
lldb
(oder vielleicht Python) erfordern, dass die Zuweisungen für first und count in separaten Zeilen erfolgen. Abgesehen davon funktioniert das super! Danke dafür!GetValueForVariablePath
wird zurückgegebenNo Value
. Ich verwende lldb-300.2.47 in Xcode 5.0. Fürint array[8]
,parry array 8
gibtNo Value
acht Mal währendprint array[0]
funktioniert wie erwartet.GetValueForVariablePath
für ,EvaluateExpression
weil ich immer noch zu sehenNo value
. Nun funktioniert ein Zeigerausdruck wie dieser :parray ((double*)sourcePointer+1) 5
. Der Rückgabetyp für beide Funktionen ist in der API-Dokumentation identisch undEvaluateExpression
scheint daher ein besserer Weg zu sein.Es scheint noch nicht unterstützt zu werden.
Sie können die Speicherlesefunktion (Speicher lesen / x) verwenden, wie z
(lldb) memory read -ff -c10 `test`
zehnmal einen Float von diesem Zeiger aus drucken. Dies sollte die gleiche Funktionalität wie @ von gdb sein.
quelle
(lldb) memory read -ff -c10 `test`
x/10f test
Ich habe versucht, einen Kommentar hinzuzufügen, aber das war nicht gut, um eine vollständige Antwort zu veröffentlichen, also habe ich meine eigene Antwort gegeben. Dies löst das Problem mit dem Erhalten von "No Value". Sie müssen den aktuellen Frame abrufen, da lldb.frame meiner Meinung nach zum Zeitpunkt des Modulimports festgelegt ist, sodass der aktuelle Frame nicht vorhanden ist, wenn Sie an einem Haltepunkt anhalten, wenn Sie das Modul aus .lldbinit laden. Die andere Version würde funktionieren, wenn Sie das Skript importieren oder neu laden, wenn Sie am Haltepunkt anhalten. Die folgende Version sollte immer funktionieren.
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) + "]")
quelle
EvaluateExpression
lldb-Variablen zugewiesen wird und der Array-Index nicht gedruckt wird. Die Ausgabe ist also Zeilen wie:(double) $68 = 0
Um Variablen zu untersuchen, können Sie den
frame variable
Befehl verwenden (fr v
ist das kürzeste eindeutige Präfix), der ein-Z
Flag hat, das genau das tut, was Sie wollen:(lldb) fr v buffer -Z5 (int64_t *) buffer = 0x000000010950c000 { (int64_t) [0] = 0 (int64_t) [1] = 0 (int64_t) [2] = 0 (int64_t) [3] = 0 (int64_t) [4] = 0 }
expression
unterstützt diese Flagge leider nichtquelle
An diesem Punkt können Sie auch Ihre eigene benutzerdefinierte C-Funktion schreiben und sie aufrufen mit:
call (int)myprint(args)
quelle