私はまだ、ARC、ブリッジング、および特定の非通行料金のブリッジ CF オブジェクトについて少し混乱しています。私の現在の混乱は、CFSocket に関するものです。私は正しくクリーンアップしていると確信していますが、分析ツールはそうではないことを教えてくれます。たぶん、私の不協和音のためにリークが見えないか、ツールが間違っているのでしょう。私はツールを非難する準備ができていないので、問題を指摘する他の目を探しています. たとえば、__bridge
所有権を自分に譲渡するためのフォームがありませんか?
私のプロジェクトでは、ARC を使用して、TCP ベースのサーバーを使用しています。このクラスを「MyServer」と呼びましょう。MyServer には、次のように定義された内部プロパティ ソケットがあります。
@property (assign) CFSocketRef socket;
このプロパティは、サーバーの実行中にソケット参照を保持します。サーバーを停止すると参照が解放され、サーバー オブジェクトが削除されます。また、サーバーの起動プロセス中に作成される潜在的なリークをクリーンアップしようとしています. 私が静的解析で問題を抱えているのはこの領域です。
サーバーは次の方法で起動されます。
- (BOOL)startServer
{
BOOL started = NO;
NSLog(@"[%@ %@] starting server on port %u", NSStringFromClass([self class]), NSStringFromSelector(_cmd),self.port);
self.lastError = nil;
if ([self createSocket]) {
started = YES;
_state = SERVER_STATE_STARTING;
};
return started;
}
このcreateSocket
メソッドは、次のようにソケットを作成します (当然)。
-(BOOL)createSocket
{
BOOL result = YES;
self.socket = CFSocketCreate(kCFAllocatorDefault, PF_INET, SOCK_STREAM,
IPPROTO_TCP, 0, NULL, NULL);
if (self.socket != NULL) {
int reuse = true;
int fileDescriptor = CFSocketGetNative(self.socket);
if (setsockopt(fileDescriptor, SOL_SOCKET, SO_REUSEADDR,
(void *)&reuse, sizeof(int)) == 0) {
struct sockaddr_in address;
memset(&address, 0, sizeof(address));
address.sin_len = sizeof(address);
address.sin_family = AF_INET;
address.sin_addr.s_addr = htonl(INADDR_ANY);
address.sin_port = htons(self.port);
CFDataRef addressData = CFDataCreate(NULL,
(const UInt8 *)&address,
sizeof(address));
if (addressData && CFSocketSetAddress(self.socket, addressData) == kCFSocketSuccess) {
self.listenHandle = [[NSFileHandle alloc] initWithFileDescriptor:fileDescriptor
closeOnDealloc:YES];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(receiveIncomingConnectionNotification:)
name:NSFileHandleConnectionAcceptedNotification
object:nil];
[self.listenHandle acceptConnectionInBackgroundAndNotify];
_state = SERVER_STATE_RUNNING;
} else {
result = NO;
[self errorWithName:@"Unable to bind socket to address."];
}
CFRelease(addressData);
} else {
[self errorWithName:@"Unable to set socket options."];
CFRelease(self.socket);
CFSocketInvalidate(self.socket);
CFRelease(self.socket);
self.socket = nil;
result = NO;
}
} else {
[self errorWithName:@"Unable to create socket."];
// CFRelease(self.socket); //NO - CFRelease(NULL) is a runtime error!
result = NO;
}
return result;
}
このコードで静的解析を実行すると、Xcode は self.socket に関する潜在的なリークを多数報告します。createSocket
上記の方法からの一例を次に示します。
このパスでオブジェクトをもう参照していないことは確かです。おそらく、私がオブジェクトを所有したいことをシステムに伝える何らかの方法があり、システムが不平を言う理由は、私が所有していることをシステムが認識できないためです。__bridge
その情報を伝えるためにキャストの1つを使用することになっていますか? プロパティを保持または強力にしようとしましたが、オブジェクトではないため構築されません。他の考えはありますか?