1. ホーム
  2. xcode

LLDBデバッガでメソッド呼び出しやコード実行を行うには?

2023-10-11 06:05:14

質問

私は print someFloatVariable ブレークポイントを設定するときや po [self someIvarHoldingAnObject] といった便利なことができない。

[self setAlpha:1];

すると、吐き出されます。

error: '[self' is not a valid command.

奇妙なことに、私は po [self someIvarHoldingAnObject] を呼び出すと、その記述が表示されることです。

私は1年前に誰かが実行時にコンソールを介してコードを実行する方法を実演したビデオを見たことがあると思いますが、私が間違っていなければ、この人は引数も提供し、ポインタにオブジェクトを割り当てました。それを行うにはどうしたらよいでしょうか。

どのように解決するのですか?

gdb v. lldb コマンドの正規のリファレンスは以下の通りです。 http://lldb.llvm.org/lldb-gdb.html

式を評価するexprコマンドを使用したいと思います。 これは、引数に加えて "生の入力" を受け取る lldb コマンドの 1 つで、(expr への) 引数が終わり、コマンドが始まる場所を示すためにしばしば "--" を必要とします。

(lldb) expr -- [self setAlpha:1]

ショートカットの "p" があり、これは -- を代わりに行ってくれます(ただし、引数は許しません)、例えば以下のように。

(lldb) p [self setAlpha:1]

呼び出す関数がプログラムの一部でない場合、lldbがそれらをどのように呼び出すかを知るために、しばしばそれらの戻り値の型を明示的に宣言する必要があるでしょう。

(lldb) p printf("hi\n")
error: 'printf' has unknown return type; cast the call to its declared return type
error: 1 errors parsing expression
(lldb) p (int)printf("hi\n")
(int) $0 = 3
hi
(lldb)

ところで、浮動小数点数の引数の問題を回避するための巧妙な方法があります。 このファイルは lldb に入力するすべての式に追加され、クラスメソッドのプロトタイプが記述されています。 例えば、私は NSObject を継承した MyClass というクラスを持っていますが、これには "setArg:" と "getArg" という二つの興味深いメソッドがあり、これらは float ivar を設定したり取得したりしています。 これはくだらない小さな例ですが、使い方を示しています。 lldbのために書いたプレフィックス・ファイルです。

@interface NSObject
@end
@interface MyClass : NSObject
- init;
- setArg: (float)arg;
- (float) getArg;
@end

extern "C" {
  int strcmp (const char *, const char *);
  int printf(const char * __restrict, ...);
  void puts (const char *);
}

で、私の ~/.lldbinit ファイルに

settings set target.expr-prefix /Users/jason/lldb-prefix.h

で、これで

(lldb)    p [var getArg]
(float) $0 = 0.5
(lldb)    p [var setArg:0.7]
(id) $1 = 0x0000000100104740
(lldb)    p [var getArg]
(float) $2 = 0.7

ここに標準的なCライブラリ関数もいくつか含まれていることにお気づきでしょう。 こうすることで、これらの関数の戻り値の型をキャストする必要がなくなります。

(lldb) p printf("HI\n")
<no result>
HI
(lldb) p strcmp ("HI", "THERE")
(int) $3 = -12

(この "<no result>" の修正は、すでに lldb TOT のソースにコミットされています)。