Я играю с Objective-C Распределенные объекты , и у меня возникают некоторые проблемы с пониманием того, как управление памятью работает в системе. Пример, приведенный ниже, иллюстрирует мою проблему:
Protocol.h
#import <Foundation/Foundation.h>
@protocol DOServer
- (byref id)createTarget;
@end
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;
}
Client.m
#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;
}
Проблема заключается в том, что любые удаленные объекты, созданные корневым прокси-сервером, не освобождаются, когда их аналоги-прокси в клиенте выходят из области видимости. Согласно документации :
Когда удаленный прокси-сервер объекта освобождается, получателю отправляется сообщение, уведомляющее его о том, что локальный объект больше не используется в соединении.
Поэтому я ожидал бы, что, поскольку каждый DOTarget
выходит из области видимости (каждый раз вокруг цикла), его удаленный аналог будет выделяться, поскольку на удаленной стороне соединения нет других ссылок на него.
На самом деле этого не происходит: временные объекты освобождаются только при выходе из клиентского приложения или, точнее, при недействительном соединении. Я могу принудительно освободить временные объекты на удаленной стороне, явно аннулируя объект NSConnection, который я использую каждый раз вокруг цикла, и создавая новый, но почему-то это просто чувствует неправильным.
Это правильное поведение от DO? Должны ли все временные объекты жить так же долго, как и соединение, которое их создало? Поэтому следует ли рассматривать соединения как временные объекты, которые должны открываться и закрываться при каждой серии запросов к серверу?
Любые идеи будут оценены.