Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cocoa/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用Objective-C分布式对象进行内存管理:我的临时实例永远存在!_Objective C_Cocoa_Memory Management_Distributed Objects - Fatal编程技术网

使用Objective-C分布式对象进行内存管理:我的临时实例永远存在!

使用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

我在玩Objective-C,在理解系统下内存管理的工作原理时遇到了一些问题。下面给出的示例说明了我的问题:

协议.h

#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-是的,这真的很奇怪。也许在连接被释放之前它们不会被清除,或者可能连接对它们进行了某种缓存?哦,好吧,对于我正在编写的代码,我可以在与服务器的“事务”期间使用临时连接。可惜的是,这感觉真的不对。感觉您应该能够在整个过程中打开与服务器的连接:特别是当您查看此类类时