如何在特定地址初始化对象(NSObject子类)

时间:2010-10-15 21:55:47

标签: objective-c ios4 sqlite nsobject

您好我需要在我指定的特定位置初始化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。 Docs说这个函数的参数必须是先前分配的指针,它就是。我不知道这是否意味着使用NSZoneMalloc / Calloc分配。

2)

id location = sqlite3_aggregate_function(...);

location = [[NSDecimalNumber alloc] init];

但这会在释放内存时导致某种无限递归...不确定交易是什么。这里的截图: http://dl.dropbox.com/u/3002073/Public%20Sync/sqlitefunctionissue.png

任何建议都将不胜感激!

2 个答案:

答案 0 :(得分: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;

另一方面,我同意马克;也许这个不可变的类不是你问题的最佳解决方案?

答案 1 :(得分:1)

你的第一个版本根本不起作用。 NSZoneFromPointer仅在传递从区域分配的指针时起作用。它被使用,因此您可以从与其他对象相同的区域分配对象。

第二个版本应该可行,但如果没有更多的背景,很难说。你传递给sqlite3_aggregate_context作为要分配的内存大小是什么?你完成后如何释放记忆?

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

NSDecimalNumber是一个不可变类,因此在它上面调用-init(而不是-initWithDecimal :)只是为了获得一些默认值。当函数进展时,您使用什么类型的代码用新值替换NSNumber?

更重要的是,为什么要使用NSDecimalNumber,而不是C整数,或者是double,还是其他什么?