Se produce una fuga de memoria al realizar una solicitud ftp en el subproceso en segundo plano

Estoy desarrollando una aplicación que puede descargar imágenes del servidor a través de una solicitud ftp y luego mostrarlas. La solicitud ftp se ejecuta en segundo plano. Cuando finalice la descarga, se enviará un mensaje de actualización a la vista.

I encountered a memory leak when doing the ftp request which has the following features:
1. The memory leak do not happen every time. May be 1 / 7.
2. If I do the ftp request on the main thread, everything is OK.
3. If I do the ftp request on simulator, everything is OK.

solía SIMPLEFTP para hacer el trabajo de ftp y he hecho algunas modificaciones para solucionar mi solicitud.

En el FtpListService.m, este archivo se utiliza para solicitar información de una lista de documentos (nombre, tamaño, fecha de modificación). Aquí se produce una fuga de memoria (resalto la línea con "####").

//This is the method to start a ftp request
- (void)_startReceive
// Starts a connection to download the current URL.
{
    BOOL                success;
    NSURL *             url;
    CFReadStreamRef     ftpStream;

    //don't tap receive twice in a row!
    assert(self.networkStream == nil);     

    // First get and check the URL.
    self.InputUrl = [self.InputUrl stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
    url = [FtpUtil smartURLForString:self.InputUrl];
    success = (url != nil);

    // If the URL is bogus, let the user know.  Otherwise kick off the connection.
    if (!success) {
        DLog(@"Bad ftp url.");
    } else {

    // Create the mutable data into which we will receive the listing.
    assert(self.listData != nil);

    // Open a CFFTPStream for the URL.
    ftpStream = CFReadStreamCreateWithFTPURL(NULL, (CFURLRef) url);

    assert(ftpStream != NULL);

    self.networkStream = (NSInputStream *) ftpStream;

    self.networkStream.delegate = self;
    [self.networkStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:RUNLOOPMODEL];

    //This timer will be called to terminate the request which is blocked for a  customed time.
    NSTimer* timer = [NSTimer scheduledTimerWithTimeInterval:TIMEOUTFTPLIST target:self
                                                    selector:@selector(listdealTimeOut:) userInfo:nil repeats:NO];

    [[NSRunLoop currentRunLoop] addTimer:timer forMode:RUNLOOPMODEL];

    [self.networkStream open];

    CFRelease(ftpStream);

    }
}

- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode
// An NSStream delegate callback that's called when events happen on our 
// network stream.
{
    connected = @"connected";

     switch (eventCode) {            //####################### EXC_BAD_ACCESS 
        case NSStreamEventOpenCompleted: {
            //NSLog(@"NSStreamEventOpenCompleted");
        } break;
        case NSStreamEventHasBytesAvailable: {
             NSInteger       bytesRead;
             uint8_t         buffer[LISTDOCBUFFER];

         // Pull some data off the network.

        bytesRead = [self.networkStream read:buffer maxLength:sizeof(buffer)];
        if (bytesRead == -1) {
            [self _stopReceiveWithStatus:@"Network read error"];
            } else if (bytesRead == 0) {
                [self _stopReceiveWithStatus:@"no more data"];
            } else {
                assert(self.listData != nil);

                // Append the data to our listing buffer.
                [self.listData appendBytes:buffer length:bytesRead];

                [self _parseListData];
            }
        } break;
        case NSStreamEventHasSpaceAvailable: {
            //NSLog(@"NSStreamEventHasSpaceAvailable");
             assert(NO);     // should never happen for the output stream
        } break;
        case NSStreamEventErrorOccurred: {
            DLog(@"NSStreamEventErrorOccurred");
            [self _stopReceiveWithStatus:@"Stream open error"];
        } break;
        case NSStreamEventEndEncountered: {
            DLog(@"NSStreamEventEndEncountered");
            // ignore
        } break;
        default: {
            DLog(@"default");
            assert(NO);
        } break;
    }

}

En FtpService.m. Aquí podría especificar la dirección y el tiempo de prueba para realizar la solicitud ftp:

- (NSArray *)requstServerListInfo:(NSString *)filename tryTime:(int)tryTime
{
    NSArray *result = nil;

   //Create the request ftp path
    NSString* tm = [NSString stringWithFormat:FTPURL];

    if(filename != nil)
        tm = [NSString stringWithFormat:@"%@%@/",FTPURL,filename];

    while (tryTime-- > 0) {

        FtpListService *listService = [[FtpListService alloc] initWithUrl:tm];

        [listService _startReceive];

        //isReceiving will be NO only when : connect error, time out, correctly done job
        //I do not really understand the loop, I just know this will cause the request job to begin
        while (listService.isReceiving) {
            [[NSRunLoop currentRunLoop] runMode:RUNLOOPMODEL beforeDate:[NSDate distantFuture]];
        }

        //if correctly request, dirArray != nil
        if(listService.dirArray == nil) {
            [listService release];
            continue;

        } else {

            result = listService.dirArray;
            [listService release];
            break;
        }
     }

    return result;
}

El trabajo ftp comienza desde PGNetConductor.m, que es un singleton:

pm = [[PGDataManagement alloc] init];
dispatch_async(dispatch_get_global_queue(0, 0), ^{
    result = [pm startNetWork];
}

PGDataManagement es propiedad de PGNetConductor: @property (nonatomic, unsafe_unretained) PGDataManagement *pm;

Intenté mucho pero no pude resolver el problema. Espero que alguien pueda darme algún consejo. Si necesitas el código o más información, dímelo. ¡Gracias!

preguntado el 12 de junio de 12 a las 16:06

No entiendo por qué su pregunta dice 'pérdida de memoria' pero su fragmento de código dice 'dirección incorrecta': ¿es una fuga de memoria o un bloqueo? -

@deanWombourne Creo que es un problema de administración de memoria lo que hace que el programa se bloquee. -

mala dirección no significa pérdida de memoria. -

0 Respuestas

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.