使用Objective-C分布式对象进行内存管理:我的临时实例永远存在!
我在玩Objective-C,在理解系统下内存管理的工作原理时遇到了一些问题。下面给出的示例说明了我的问题: 协议.h使用Objective-C分布式对象进行内存管理:我的临时实例永远存在!,objective-c,cocoa,memory-management,distributed-objects,Objective C,Cocoa,Memory Management,Distributed Objects,我在玩Objective-C,在理解系统下内存管理的工作原理时遇到了一些问题。下面给出的示例说明了我的问题: 协议.h #import <Foundation/Foundation.h> @protocol DOServer - (byref id)createTarget; @end #导入 @协议服务器 -(byref id)createTarget; @结束 Server.m #import <Foundation/Foundation.h> #import
#import <Foundation/Foundation.h>
@protocol DOServer
- (byref id)createTarget;
@end
#导入
@协议服务器
-(byref id)createTarget;
@结束
Server.m
#import <Foundation/Foundation.h>
#import "Protocol.h"
@interface DOTarget : NSObject
@end
@interface DOServer : NSObject < DOServer >
@end
@implementation DOTarget
- (id)init
{
if ((self = [super init]))
{
NSLog(@"Target created");
}
return self;
}
- (void)dealloc
{
NSLog(@"Target destroyed");
[super dealloc];
}
@end
@implementation DOServer
- (byref id)createTarget
{
return [[[DOTarget alloc] init] autorelease];
}
@end
int main()
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
DOServer *server = [[DOServer alloc] init];
NSConnection *connection = [[NSConnection new] autorelease];
[connection setRootObject:server];
if ([connection registerName:@"test-server"] == NO)
{
NSLog(@"Failed to vend server object");
}
else
{
while (YES)
{
NSAutoreleasePool *innerPool = [[NSAutoreleasePool alloc] init];
[[NSRunLoop currentRunLoop] runUntilDate:
[NSDate dateWithTimeIntervalSinceNow:0.1f]];
[innerPool drain];
}
}
[pool drain];
return 0;
}
#import <Foundation/Foundation.h>
#import "Protocol.h"
int main()
{
unsigned i = 0;
for (; i < 3; i ++)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
id server = [NSConnection rootProxyForConnectionWithRegisteredName:@"test-server"
host:nil];
[server setProtocolForProxy:@protocol(DOServer)];
NSLog(@"Created target: %@", [server createTarget]);
[[NSRunLoop currentRunLoop] runUntilDate:
[NSDate dateWithTimeIntervalSinceNow:1.0]];
[pool drain];
}
return 0;
}
#导入
#导入“Protocol.h”
@接口DOTarget:NSObject
@结束
@接口DOServer:NSObject
@结束
@实现目标
-(id)init
{
if((self=[super init]))
{
NSLog(@“已创建目标”);
}
回归自我;
}
-(无效)解除锁定
{
NSLog(@“目标已销毁”);
[super dealoc];
}
@结束
@实现DOServer
-(byref id)createTarget
{
返回[[[DOTarget alloc]init]autorelease];
}
@结束
int main()
{
NSAutoreleasePool*池=[[NSAutoreleasePool alloc]init];
DOServer*server=[[DOServer alloc]init];
NSConnection*connection=[[NSConnection new]autorelease];
[连接setRootObject:服务器];
if([连接注册表名:@“测试服务器”]==否)
{
NSLog(@“无法出售服务器对象”);
}
其他的
{
虽然(是)
{
NSAutoreleasePool*innerPool=[[NSAutoreleasePool alloc]init];
[[nsrunlop currentRunLoop]运行时间:
[NSDate DATE WITH TIME INTERVALICENSNOW:0.1f]];
[池内排水沟];
}
}
[泳池排水沟];
返回0;
}
客户端.m
#import <Foundation/Foundation.h>
#import "Protocol.h"
@interface DOTarget : NSObject
@end
@interface DOServer : NSObject < DOServer >
@end
@implementation DOTarget
- (id)init
{
if ((self = [super init]))
{
NSLog(@"Target created");
}
return self;
}
- (void)dealloc
{
NSLog(@"Target destroyed");
[super dealloc];
}
@end
@implementation DOServer
- (byref id)createTarget
{
return [[[DOTarget alloc] init] autorelease];
}
@end
int main()
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
DOServer *server = [[DOServer alloc] init];
NSConnection *connection = [[NSConnection new] autorelease];
[connection setRootObject:server];
if ([connection registerName:@"test-server"] == NO)
{
NSLog(@"Failed to vend server object");
}
else
{
while (YES)
{
NSAutoreleasePool *innerPool = [[NSAutoreleasePool alloc] init];
[[NSRunLoop currentRunLoop] runUntilDate:
[NSDate dateWithTimeIntervalSinceNow:0.1f]];
[innerPool drain];
}
}
[pool drain];
return 0;
}
#import <Foundation/Foundation.h>
#import "Protocol.h"
int main()
{
unsigned i = 0;
for (; i < 3; i ++)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
id server = [NSConnection rootProxyForConnectionWithRegisteredName:@"test-server"
host:nil];
[server setProtocolForProxy:@protocol(DOServer)];
NSLog(@"Created target: %@", [server createTarget]);
[[NSRunLoop currentRunLoop] runUntilDate:
[NSDate dateWithTimeIntervalSinceNow:1.0]];
[pool drain];
}
return 0;
}
#导入
#导入“Protocol.h”
int main()
{
无符号i=0;
对于(;i<3;i++)
{
NSAutoreleasePool*池=[[NSAutoreleasePool alloc]init];
id服务器=[NSConnection rootProxyForConnectionWithRegisteredName:@“测试服务器”
主持人:无];
[server setProtocolForProxy:@protocol(DOServer)];
NSLog(@“已创建目标:%@,[server createTarget]);
[[nsrunlop currentRunLoop]运行时间:
[NSDate DATE WITH TIME INTERVALICENSNOW:1.0]];
[泳池排水沟];
}
返回0;
}
问题是,当客户端中的代理对应项超出范围时,根代理创建的任何远程对象都不会被释放。根据:
解除分配对象的远程代理时,将向接收方发送一条消息,通知其不再通过连接共享本地对象
因此,我希望当每个DOTarget
都超出范围时(每次在循环中),它的远程对应项将被删除,因为在连接的远程端没有对它的其他引用
实际上,这并没有发生:只有当客户端应用程序退出时,或者更准确地说,当连接失效时,才会释放临时对象。我可以通过显式地使循环中每次使用的NSConnection对象无效并创建一个新对象来强制解除远程端的临时对象的分配,但不知何故,这感觉是错误的
这是DO的正确行为吗?所有临时对象是否应该与创建它们的连接一样长?因此,连接是否被视为临时对象,应在针对服务器的每一系列请求中打开和关闭
如有任何见解,将不胜感激 服务器上的自动释放池永远不会耗尽,因此自动释放的对象永远不会“超出范围”。你总是会有一个额外的参考他们。与在客户机中设置的测试类似,设置您的服务器(让运行循环每隔一秒左右转储一次),每次都排出并建立一个新的内部池。然后您将看到预期的结果。尝试根本不调用“自动释放”。只需允许“createTarget”返回而不保留,并假设在客户端上释放代理时对象将被释放。当连接对象执行它的神奇操作并将代理返回给客户端时,它会在其“localObjects”属性中保留服务器本地对象。这样,当客户端的代理超出范围时,连接将释放本地对象,无需自动释放 我不确定我是否正确,但这似乎是一个有效的解释,虽然不调用自动释放似乎有点奇怪,但这是DO,这有点不同。即使服务器实际上正在创建对象,但它并不拥有它,因为客户端创建了它(尽管是远程创建的)
- 客户机拥有该对象,因为它创建了该对象
- 客户负责保留/释放代理
- 服务器生命周期中的代理和对象是同一个
- 所有内存管理应由发起分配的同一实体(在本例中为客户机)完成
- 远程创建对象时切勿使用“便利”方法,因为这将调用自动释放
当客户端创建内存时,关于如何处理内存的解释是如此之少,真是太可怜了。@Jason Coco:你确定吗?我似乎得到了相同的结果…也许我的服务器代码仍然是错误的?查看更新后的代码……另外,我从一个真正的Cocoa应用程序中提取了问题,因此在该实例中,所有问题都在主线程上运行-[NSApplication run],其中每个runloop迭代都会耗尽池。@jkp-是的,这真的很奇怪。也许在连接被释放之前它们不会被清除,或者可能连接对它们进行了某种缓存?哦,好吧,对于我正在编写的代码,我可以在与服务器的“事务”期间使用临时连接。可惜的是,这感觉真的不对。感觉您应该能够在整个过程中打开与服务器的连接:特别是当您查看此类类时