LLDB中的View数组:相当于Xcode 4.1中GDB的'@'运算符

mid*_*azz 71 debugging xcode llvm xcode4 lldb

我想查看指针指向的元素数组.在GDB中,这可以通过使用运算符'@'将指向的内存视为给定长度的人工数组来完成

*pointer @ length
Run Code Online (Sandbox Code Playgroud)

length我想要查看的元素数量在哪里.

上述语法在随Xcode 4.1提供的LLDB中不起作用.

有什么方法可以在LLDB中完成上述工作吗?

Siy*_*Ren 122

实际上有一种简单的方法,通过将指针转换为指向数组的指针.

例如,如果你有一个int* ptr,并且想要将其视为十个整数的数组,那么你可以这样做

p *(int(*)[10])ptr
Run Code Online (Sandbox Code Playgroud)

因为它仅依赖于标准C功能,所以此方法无需任何插件或特殊设置即可运行.它同样适用于其他调试器,如GDB或CDB,即使它们也有专门的打印数组语法.

  • 对于那些使用Xcode GUI但只有指针显示第一个数据元素的人,请执行以下操作:`右键单击数据指针>将值视为...>自定义类型...`在表达式字段中放置`*(double(*)[10])value_type`.这将打印出指向的10个值.您可以将double和10修改为您想要的类型/数量. (21认同)
  • 这是一个很好的答案 - 值得更多的赞成.不需要自定义脚本或任何东西,甚至可以使用结构. (3认同)

Jim*_*ham 30

从Xcode 8.0中的lldb开始,有一个新的内置parray命令.所以你可以说:

(lldb) parray <COUNT> <EXPRESSION>
Run Code Online (Sandbox Code Playgroud)

打印由结果指向的内存EXPRESSION作为COUNT表达式指向的类型的元素数组.

如果计数存储在当前帧中可用的变量中,请记住您可以执行以下操作:

(lldb) parray `count_variable` pointer_to_malloced_array
Run Code Online (Sandbox Code Playgroud)

这是一个通用的lldb功能,在反引号中包围的lldb中的任何命令行参数都会被计算为一个返回整数的表达式,然后在命令执行之前将整数替换为参数.


Mar*_*n R 26

我发现的唯一方法是通过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)
Run Code Online (Sandbox Code Playgroud)

在lldb中定义命令"parray":

(lldb) command script import /path/to/parray.py
(lldb) command script add --function parray.parray parray
Run Code Online (Sandbox Code Playgroud)

现在你可以使用"parray variable length ":

(lldb) parray a 5
(double) *a = 0
(double) [1] = 0
(double) [2] = 1.14468
(double) [3] = 2.28936
(double) [4] = 3.43404
Run Code Online (Sandbox Code Playgroud)

  • 提示:如果您需要在修改后重新加载脚本,请键入"script reload(parray)"(参见http://www.libertypages.com/clarktech/?p=4303) (2认同)

dav*_*idA 15

使用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]
Run Code Online (Sandbox Code Playgroud)

此示例假定'pointer'是一个包含64个浮点数的数组: float pointer[64];

  • 我真的不懂任何东西,但它有效并且非常有用!你在哪里学到如此棒的lldb技巧? (2认同)

w-m*_*w-m 12

它似乎还没有得到支持.

您可以使用内存读取功能(内存读取/ x),如

(lldb) memory read -ff -c10 `test`
Run Code Online (Sandbox Code Playgroud)

从该指针打印浮动十次.这应该与gdb的@具有相同的功能.

  • 您可以使用反引号来计算指针表达式,例如:`(lldb)内存读取-ff -c10 \`test \`` (2认同)

小智 12

从Martin R回答开始我改进了如下:

  1. 如果指针不是简单变量,例如:

    struct {
      int* at;
      size_t size;
    } a;
    
    Run Code Online (Sandbox Code Playgroud)

    然后"parray a.at 5"失败.

    我通过将"FindVariable"替换为"GetValueForVariablePath"来修复此问题.

  2. 现在如果数组中的元素是聚合,例如:

    struct {
      struct { float x; float y; }* at;
      size_t size;
    } a;
    
    Run Code Online (Sandbox Code Playgroud)

    然后"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. 添加了一个可选的"第一个"参数(用法:parray [FIRST] COUNT),这在您拥有大量元素时非常有用.

  4. 让它在init执行"命令脚本添加-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')
Run Code Online (Sandbox Code Playgroud)


小智 5

我尝试添加评论,但这对于发布完整答案并不好,所以我做出了自己的答案。这解决了获得“无价值”的问题。您需要获取当前帧,因为我相信 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) + "]")
Run Code Online (Sandbox Code Playgroud)


Hol*_*ger 5

要检查变量,您可以使用命令frame variablefr v是最短的唯一前缀),该命令有一个-Z标志可以完全满足您的要求:

(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
}
Run Code Online (Sandbox Code Playgroud)

不幸的expression是不支持该标志