7

objcメソッドが戻ったときに起動するアクションを作成しました(objc ::: return)。今のところ、戻り値を取得する必要があります。出来ますか?

4

1 に答える 1

5

要約すると、いいえ、DTraceプローブでObjective-Cメソッドの戻り値を取得することはできません。

Bill Bumgarnerは、メッセージをnilにトレースすることについて投稿しており、次のように述べています。

余談ですobjc_msgSend()が、現時点では、dtraceを介してリターンをトレースすることはできません。関数が実際に返されないことを考えると、当然のことです。dtraceに関する限り、これは前文にすぎません。

ブログ投稿はかなり古く(2008年1月)、objcプロバイダーではなくpidプロバイダーを使用しています。とはいえ、Mac OS X v10.7.1の時点でも有効であり、objcプロバイダーにも適用されます。

面白いことに、それは時々機能するように見えるかもしれませんが、DTraceがRAXレジスタを読み取るタイミングによって異なります。が返されないためobjc_msgSend()、DTraceは、トレースされているメソッドの戻りであるとは限らないコードによって格納されたRAXの値を使用することになります。

次のコードを検討してください。

NSNumber *n = [NSNumber numberWithInt:1234];
printf("n has address %p\n", n);

および次のプローブ:

objc$target:NSPlaceholderNumber:-initWithInt?:return
{
    printf("Returning from -[NSPlaceholderNumber initWithInt:]\n");
    printf("\treturn value = 0x%p\n", (void *)arg1);
}

DTraceを使用して実行すると、次の出力が得られます。

n has address 0x4d283
Returning from -[NSPlaceholderNumber initWithInt:]
    return value = 0x4d283

したがって、プローブはの戻り値をキャプチャできたようです-initWithInt:。ただし、これは運だけです。おそらく、によって呼び出され、期待値をRAXに配置する関数(CFNumberCreate()または)が原因である可能性があります。CFMakeCollectable()-initWithInt:

ここで、次のコードについて考えてみます。

char *c = "hello";
NSData *data = [NSData dataWithBytes:c length:strlen(c)];
NSString *s = [[NSString alloc] initWithData:data
                                    encoding:NSASCIIStringEncoding];
printf("s has address %p\n", s);

および次のプローブ:

objc$target:NSPlaceholderString:-initWithData?encoding?:return
{
    printf("Returning from -[NSPlaceholderString initWithData:encoding:]\n");
    printf("\treturn value = 0x%p\n", (void *)arg1);
}

DTraceを使用して実行すると、次の出力が得られます。

s has address 0x7fcd92414ea0
Returning from -[NSPlaceholderString initWithData:encoding:]
    return value = 0x600

ご覧のとおり、アドレス(つまり戻り値)が一致していません。実際、0x600は、のCoreFoundationのkCFStringEncodingASCII対応物である値ですNSASCIIStringEncoding。ある時点で、メソッドまたはメソッドによって呼び出された関数のいずれかが0x600をRAXに移動しました。これは、DTraceが誤って戻り値と見なした値です。

于 2011-09-03T00:54:37.933 に答える