Ich möchte eine Reihe von Elementen anzeigen, auf die ein Zeiger zeigt. In GDB kann dies durch Behandeln des Pointed Memory als künstliches Array einer bestimmten Länge unter Verwendung des Operators '@' als geschehen
*pointer @ length
dabei ist length
die Anzahl der Elemente, die ich anzeigen möchte.
Die obige Syntax funktioniert in der mit Xcode 4.1 gelieferten LLDB nicht.
Gibt es eine Möglichkeit, wie das oben genannte in LLDB erreicht werden kann?
Tatsächlich gibt es eine einfache Möglichkeit, dies zu tun, indem Sie den Zeiger auf ein Zeiger-zu-Array umwandeln.
Wenn Sie zum Beispiel ein int* ptr
, und Sie möchten es als Array von zehn Ganzzahlen anzeigen, können Sie tun
p *(int(*)[10])ptr
Diese Methode funktioniert ohne Plugins oder spezielle Einstellungen, da sie nur auf Standard-C-Funktionen basiert. Es funktioniert ebenfalls mit anderen Debuggern wie GDB oder CDB, obwohl sie auch spezielle Syntaxen zum Drucken von Arrays haben.
Beginnend mit der lldb in Xcode 8.0 gibt es einen neuen eingebauten Parray-Befehl. Sie können also sagen:
(lldb) parray <COUNT> <EXPRESSION>
um den Speicher, auf den das Ergebnis von EXPRESSION
zeigt, als Array von COUNT
Elementen des Typs zu drucken, 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 in Backticks enthaltene Befehlszeilenargument in lldb wird als Ausdruck ausgewertet, der eine Ganzzahl zurückgibt. Anschließend wird das Argument vor der Befehlsausführung durch die Ganzzahl ersetzt.
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)
Definiere 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 Länge" verwenden:
(lldb) parray a 5
(double) *a = 0
(double) [1] = 0
(double) [2] = 1.14468
(double) [3] = 2.28936
(double) [4] = 3.43404
Mit Xcode 4.5.1 (das Ihnen jetzt vielleicht hilft oder auch 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 angenommen, dass 'pointer' ein Array von 64 Floats ist: float pointer[64];
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 das 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 gibt "parray a.at 5" aus: 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) + "]" in der Schleife aufgelöst habe, anstatt "a.at" aufzulösen und dann die untergeordneten Elemente abzurufen.
Ein optionales Argument "first" (Verwendung: parray [FIRST] COUNT) wurde hinzugefügt. Dies ist nützlich, wenn Sie über eine große Anzahl von Elementen verfügen.
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')
Es scheint noch nicht unterstützt zu werden.
Sie könnten die Speicherlesefunktion (memory read/x) verwenden, wie z
(lldb) memory read -ff -c10 `test`
um einen Gleitkomma zehnmal von diesem Zeiger aus zu drucken. Dies sollte die gleiche Funktionalität sein wie gdbs @.
Ich habe versucht, einen Kommentar hinzuzufügen, aber das war nicht besonders gut, um eine vollständige Antwort zu veröffentlichen, also habe ich meine eigene Antwort abgegeben. Dies löst das Problem mit "No Value". Sie müssen den aktuellen Frame abrufen, da lldb.frame meines Erachtens zum Zeitpunkt des Modulimports festgelegt ist, sodass er nicht den aktuellen Frame enthält, wenn Sie an einem Haltepunkt anhalten, wenn Sie das Modul aus .lldbinit laden. Die andere Version würde funktionieren, wenn Sie das Skript beim Anhalten am Haltepunkt importieren oder neu laden. 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) + "]")
Nun, an diesem Punkt können Sie auch Ihre eigene benutzerdefinierte C-Funktion schreiben und sie aufrufen mit:
call (int)myprint(args)
Um Variablen zu untersuchen, können Sie das frame variable
Befehl (fr v
ist das kürzeste eindeutige Präfix) mit einem -Z
Flag, 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
}
leider unterstützt expression
dieses Flag nicht