2

嗨,我需要在我指定的特定位置初始化一个 NSObject(例如,通过 void* 指针)。对于一点上下文,我正在编写一个 sqlite3 聚合函数。为了保留这个函数的临时结果,我必须调用一个 sqlite3_aggregate_context 函数,它为我分配一块内存。我想在这个位置存储一个 NSDecimalNumber。

到目前为止,我尝试了两种方法:

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

您无法真正可靠地确定将在内存中创建对象的位置。NSZoneFromPointer 对您来说失败了,因为 sqlite3 API 没有使用区域来分配其资源。

如果您希望能够传递特定位置,则应该使用指向对象的指针来执行此操作(因此您基本上存储了指向指针的指针)。然后,您可以从聚合函数中读取此信息并进行相应更新。只要确保你不要简单地让你的对象在调用结束时被释放而不注意释放它(否则你会有泄漏)。

因此,例如,您可以执行以下操作:

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 仅在传递从区域分配的指针时才有效。使用它是为了让您可以从与其他对象相同的区域分配一个对象。

第二个版本应该可以工作,尽管没有更多上下文很难说。您将什么传递给 sqlite3_aggregate_context 作为要分配的内存大小?完成后如何释放内存?

第二个版本不起作用,因为“id”类型实际上是一个指针,所以你将它指向 sqlite3_aggregate_context() 返回的内存,然后将它指向 alloc/init 返回的内存。你真的需要存储一个指向指针的指针才能让它以你想要的方式工作。

NSDecimalNumber 是一个不可变的类,所以在它上面调用 -init(而不是 -initWithDecimal:) 只会给你一些默认值。随着函数的进行,您使用哪种代码将 NSNumber 替换为新值?

更重要的是,为什么要使用 NSDecimalNumber,而不是 C 整数、双精度数或其他什么?

于 2010-10-15T22:11:52.220 回答