2012-10-01 17 views
8

Me di cuenta de que estaba obteniendo errores aleatorios EXC_BADACCESS al usar CFStreamCreatePairWithSocketToHost en mi programa, pero solo con ios6 - cuando se usa el simulador ios5 (incluso dentro de ios6sdk con xcode4.5) todo funciona bien. Terminé extrayendo el problema en un pequeño programa de prueba que sigue: si activa malloc guard con esto, explotará de inmediato (consulte el bloqueo a continuación). También esto sucede w/arc y non-arc.CFStreamCreatePairWithSocketToHost roto con el simulador ios6?

@interface PHAppDelegate : UIResponder <UIApplicationDelegate, NSStreamDelegate> 
{ 
    NSOutputStream*  mOutputStream; 
    NSInputStream*  mInputStream; 
} 

@implementation PHAppDelegate 

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
{ 
    NSString* testAddress = @"192.168.1.0"; 
    [self openWithHost:testAddress port:444]; 
    return YES; 
} 

- (void)openWithHost:(NSString*)host port:(int)port 
{ 
    CFReadStreamRef readStream; 
    CFWriteStreamRef writeStream; 

    CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, 
             (CFStringRef)host, /*ip_addr*/ 
             port, 
             &readStream, 
             &writeStream); 

    mInputStream = (NSInputStream *)readStream; 
    mOutputStream = (NSOutputStream *)writeStream; 

    if (mInputStream == nil) 
    { 
     NSLog(@"couldn't create the inputStream using CFStreamCreatePairWithSocketsToHost()"); 
     return; 
    } 

    if (mOutputStream == nil) 
    { 
     NSLog(@"couldn't create the outputstream using CFStreamCreatePairWithSocketsToHost()"); 
     return; 
    } 

    [mInputStream setDelegate:self]; 
    [mOutputStream setDelegate:self]; 

    [mInputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; 
    [mOutputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; 

    [mInputStream open]; 
    [mOutputStream open]; 
} 

#pragma mark NSStream delegate methods 

- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode 
{ 
    NSLog(@"stream-handleEvent"); 
} 

@end 

accidente en hilo de com.apple.networking.connection:

#0 0x04b35140 in tcp_connection_destination_prepare_complete() 
#1 0x04b34fee in tcp_connection_destination_start() 
#2 0x04b34c2b in tcp_connection_start_next_destination() 
#3 0x04b33c70 in tcp_connection_handle_reachability_changed() 
#4 0x04b30a95 in __tcp_connection_start_block_invoke_0() 
#5 0x049fa53f in _dispatch_call_block_and_release() 
#6 0x04a0c014 in _dispatch_client_callout() 
#7 0x049fc418 in _dispatch_queue_drain() 
#8 0x049fc2a6 in _dispatch_queue_invoke() 
#9 0x049fd280 in _dispatch_root_queue_drain() 
#10 0x049fd450 in _dispatch_worker_thread2() 
#11 0x94e7de12 in _pthread_wqthread() 
#12 0x94e65cca in start_wqthread() 

EXC_BADACCESS @ address 0x04b35140 
0x04b3513b <+0072> call 0x4b332de <tcp_connection_destination_list_remove> 
0x04b35140 <+0077> mov 0x28(%esi),%eax 
0x04b35143 <+0080> test %eax,%eax 
+0

Tengo el mismo problema que sucede en iOS 6 pero no sucederá en iOS 5, ¿verdad tener alguna actualización? –

+0

sin actualización - todavía ocurre. – jazios

Respuesta

0

tengo código muy similar que funciona para mí en iOS 5.x y 6.x de iOS La única diferencia es que inicializo CFReadStreamRef y CFWriteStreamRef a NULL antes de llamar al CFStreamCreatePairWithSocketToHost y paso NULL para el asignador. También normalmente agrego el código como una categoría en NSStream para mayor comodidad. Por lo tanto, el código es como la siguiente:

+ (void)createStreamsToHostNamed:(NSString*)hostName port:(NSInteger)port inputStream:(NSInputStream* __autoreleasing *)inputStream outputStream:(NSOutputStream* __autoreleasing *)outputStream { 
    CFReadStreamRef readStream = NULL; 
    CFWriteStreamRef writeStream = NULL; 

    // Create a pair of of streams for a socket to the host specified 
    CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef)hostName, port, &readStream, &writeStream); 

    // Assign the output parameters 
    *inputStream = (__bridge_transfer NSInputStream*)readStream; 
    *outputStream = (__bridge_transfer NSOutputStream*)writeStream; 
} 

debe invocar el método con un poco de código como este:

@interface SomeClass : NSObject <NSStreamDelegate> 
@end 

@implementation SomeClass { 
    NSInputStream* _inputStream; 
    NSOutputStream* _outputStream; 
} 

- (void)_setupMethod { 
    __autoreleasing NSInputStream* autoreleasingInputStream = nil; 
    __autoreleasing NSOutputStream* autoreleasingOutputStream = nil; 
    [NSStream createStreamsToHostNamed:kHostConstant port:kPortConstant inputStream:&autoreleasingInputStream outputStream:&autoreleasingOutputStream]; 

    if(autoreleasingInputStream != nil && autoreleasingOutputStream != nil) { 
     _inputStream = autoreleasingInputStream; 
     [_inputStream setDelegate:self]; 
     [_inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; 
     _outputStream = autoreleasingOutputStream; 
     [_outputStream setDelegate:self]; 
     [_outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; 

     [_inputStream open]; 
     [_outputStream open]; 
    } 
} 

// NSStreamDelegate methods ... 

@end