我想查看一个指针指向的元素数组。在GDB中,可以通过使用操作符'@'将指向的内存视为给定长度的人工数组来完成。
*pointer @ length
length
我要查看的元素数量在哪里。
上面的语法在Xcode 4.1随附的LLDB中不起作用。
有什么方法可以在LLDB中完成上述工作吗?
Answers:
在lldb中,有两种方法可以做到这一点。
最常见的是,您使用parray
lldb命令,该命令使用aCOUNT
和an EXPRESSION
; EXPRESSION
被评估并且应该导致指向内存的指针。lldb然后将COUNT
在该地址打印该类型的项目。例如
parray 10 ptr
哪里ptr
是类型int *
。
或者,可以通过将指针转换为指向数组的指针来完成此操作。
例如,如果您有一个int* ptr
,并且想要将其查看为十个整数的数组,则可以执行
p *(int(*)[10])ptr
由于此方法仅依赖于标准C功能,因此无需任何插件或特殊设置即可使用。它也可以与其他调试器(例如GDB或CDB)一起使用,即使它们也具有用于打印数组的专用语法。
right click on data pointer > View value as... > Custom Type...
在expression字段put中*(double(*)[10])value_type
。这将打印出所指向的10个值。您可以将double和10修改为所需的类型/数量。
从Xcode 8.0中的lldb开始,有一个新的内置parray命令。所以你可以说:
(lldb) parray <COUNT> <EXPRESSION>
将由结果指向的内存打印EXPRESSION
为数组COUNT
将表达式为表达式指向的类型元素。
如果计数存储在当前帧中可用的变量中,请记住您可以执行以下操作:
(lldb) parray `count_variable` pointer_to_malloced_array
这是lldb的常规功能,在lldb中用反引号括起来的任何命令行参数都将被评估为返回整数的表达式,然后在执行命令之前将整数替换为该参数。
command alias
来创建快捷方式。
我发现的唯一方法是通过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)
在lldb中定义命令“ parray”:
(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
AttributeError: 'NoneType' object has no attribute 'FindVariable'
使用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];
从Martin R回答开始,我将其改进如下:
如果指针不是简单变量,例如:
struct {
int* at;
size_t size;
} a;
然后“ parray a.at 5”失败。
我通过将“ FindVariable”替换为“ GetValueForVariablePath”来解决此问题。
现在,如果数组中的元素是集合,例如:
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”,然后获取其子级。
添加了一个可选的“ first”参数(用法:parray [FIRST] COUNT),该参数在您具有大量元素时非常有用。
使它在初始化时执行“命令脚本添加-f parray.parray parray”
这是我的修改版本:
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')
lldb
(或Python)要求对first和count的分配位于单独的行上。除此之外,这很好用!谢谢你!
GetValueForVariablePath
返回No Value
。我在Xcode 5.0中使用lldb-300.2.47。对于int array[8]
,在按预期方式工作时parry array 8
返回No Value
八次print array[0]
。
GetValueForVariablePath
,EvaluateExpression
因为我仍然在看No value
。现在,像这样的指针表达作品:parray ((double*)sourcePointer+1) 5
。根据API文档,这两个函数的返回类型相同,因此EvaluateExpression
似乎是更好的方法。
我试图添加评论,但这对于发布完整答案不是很好,所以我做出了自己的答案。这解决了获得“无价值”的问题。您需要获取当前帧,因为我相信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) + "]")
EvaluateExpression
分配给lldb变量,并且不打印数组索引。因此,输出如下所示:(double) $68 = 0
好了,您最好编写自己的自定义C函数并使用以下命令调用它:
call (int)myprint(args)