2

こんにちは、指定した特定の場所で NSObject を初期化する必要があります (たとえば、void* ポインターを介して)。ちょっとした文脈のために、私はsqlite3集計関数を書いています。この関数から一時的な結果を保持するには、メモリ ブロックを割り当てる sqlite3_aggregate_context 関数を呼び出す必要があります。この場所に NSDecimalNumber を格納したいと思います。

これまでのところ、次の 2 つのアプローチを試しました。

1) allocWithZone: 次のように実行します。

void *location = sqlite3_aggregate_context(...); //returns a block of allocated memory of a certain size

NSDecimalNumber *num = [[NSDecimalNumber allocWithZone:NSZoneFromPointer(location)] initWithInt:0];

NSZoneFromPointer が nil を返すため、これは機能しません。ドキュメントによると、この関数への引数は、以前に割り当てられたポインターである必要があります。これが NSZoneMalloc/Calloc を使用して割り当てられることを意味するかどうかはわかりません。

2)

id location = sqlite3_aggregate_function(...);

location = [[NSDecimalNumber alloc] init];

しかし、これにより、メモリを解放するときにある種の無限再帰が発生します...何が問題なのかわかりません。ここのスクリーンショット: http://dl.dropbox.com/u/3002073/Public%20Sync/sqlitefunctionissue.png

どんな提案でも大歓迎です!

4

2 に答える 2

4

オブジェクトがメモリ内のどこに作成されるかを確実に判断することはできません。sqlite3 API はリソースの割り当てにゾーンを使用していないため、NSZoneFromPointer は失敗します。

特定の場所を渡すことができるようにしたい場合は、オブジェクトへのポインターを使用して行う必要があります (したがって、基本的にポインターへのポインターを格納しています)。その後、集計関数からこの情報を読み取り、それに応じて更新できます。オブジェクトを解放するのを気にせずに、呼び出しの最後にオブジェクトを単純に解放させないようにしてください (そうしないと、リークが発生します)。

したがって、たとえば、次のようなことができます。

NSDecimalNumber** numberLocation = sqlite3_aggregate_context(...);
*numberLocation = [[NSDecimalNumber alloc] initWithDouble:25.0];

オブジェクトへの参照が特別なメモリ領域に保存され、いつでもアクセスできるようになりました。

NSDecimalNumber* storedNumber = *numberLocation;
NSDecimalNumber* computedNumber = [[NSDecimalNumber alloc] initWithDouble:[storedNumber doubleValue] * someComputation];
[storedNumber autorelease];
*numberLocation = computedNumber;

一方、私はマークに同意します。おそらく、この不変クラスはあなたの問題に対する最良の解決策ではないでしょうか?

于 2010-10-15T22:15:10.757 に答える
1

最初のバージョンはまったく機能しません。NSZoneFromPointer は、ゾーンから割り当てられたポインターが渡された場合にのみ機能します。他のオブジェクトと同じゾーンからオブジェクトを割り当てることができるように使用されます。

2 番目のバージョンは機能するはずですが、これ以上のコンテキストがないと判断するのは困難です。割り当てるメモリのサイズとして sqlite3_aggregate_context に何を渡していますか? 作業が終わったら、どのようにそのメモリを解放していますか?

「id」型は実際にはポインターであるため、2 番目のバージョンは機能しません。そのため、sqlite3_aggregate_context() によって返されたメモリをポイントしてから、alloc/init によって返されたメモリをポイントしています。思い通りに動作させるには、ポインターツーポインターを格納する必要があります。

NSDecimalNumber は不変クラスであるため、(-initWithDecimal: ではなく) -init を呼び出すと、デフォルト値が取得されます。関数が進行するにつれて NSNumber を新しい値に置き換えるために、どのような種類のコードを使用していますか?

さらに言えば、C の整数や double などではなく、なぜ NSDecimalNumber を使用するのでしょうか。

于 2010-10-15T22:11:52.220 に答える