цель c получает ошибку EXC_BAD_ACCESS в обработчике завершения - PullRequest
1 голос
/ 30 мая 2019

Я новичок в Objective-C, пожалуйста, потерпите меня, если я задаю глупые вопросы :) Следующее является частью кода, я должен запустить туннель vpn, но продолжает получать ошибку EXC_BAD_ACCESS

- (void)startTunnelWithOptions:(NSDictionary *)options completionHandler:(void (^)(BOOL * error))completionHandler {

    vpnAdapter = [[OpenAdapter alloc] init];
    vpnAdapter.delegate = self;

    // get config

    config = [[NSDictionary alloc] init];

    NETunnelProviderProtocol *protocol = (NETunnelProviderProtocol *)self.protocolConfiguration;
    config = protocol.providerConfiguration;

    host = config[@"server"];

    // Load config data
    username = config[@"username"];
    password = config[@"password"];


    if(option != nil){
        [vpnAdapter connect:host user:username pass:password add:YES completionHandler:^(BOOL success){
           // return success;
            completionHandler(&success); // Thread 2: EXC_BAD_ACCESS (code=1, address=0xbcc68f020)
        }];

    }else{
        [vpnAdapter connect:host user:username pass:password add:NO completionHandler:^(BOOL success){

            completionHandler(&success);

        }];
    } 
}

Вот метод подключения

- (void)connect: (NSString *) host user:(NSString *)username pass:(NSString *) password add:(Boolean) isAdd completionHandler:(void (^)(BOOL success)) completionHandler{

    dispatch_queue_attr_t attributes = dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_UTILITY, 0);
    dispatch_queue_t connectQueue = dispatch_queue_create("me.ss-abramchuk.open-adapter.connection", attributes);
    dispatch_async(connectQueue, ^{
        // Call connect
        //int ret=1;
        NSArray* options = [NSArray arrayWithObjects:
                            @"--user", username,
                            host,
                            nil];

        if(isAdd){
            options = [NSArray arrayWithObjects:
                       @"--user", username,
                       @"--protocol", @"ad",
                       host,
                       nil];
        }
        //NSArray *paths = NSSearchPathForDirectoriesInDomains
        (NSDocumentDirectory, NSUserDomainMask, YES);
        //NSString *documentsDirectory = [paths objectAtIndex:0];

        NSMutableArray *arguments = [NSMutableArray arrayWithCapacity:1+[options count]];
        [arguments addObject:@"connect"];
        [arguments addObjectsFromArray:options];

        int argc = [arguments count];
        char **argv = (char **)malloc(sizeof(char*) * (argc + 1));

        [arguments enumerateObjectsUsingBlock:^(NSString *option, NSUInteger i, BOOL *stop) {
            const char * c_string = [option UTF8String];
            int length = (int)strlen(c_string);
            char *c_string_copy = (char *) malloc(sizeof(char) * (length + 1));
            strcpy(c_string_copy, c_string);
            argv[i] = c_string_copy;
        }];
        argv[argc] = NULL;
        const char *cfPass=[password UTF8String];
        int ret = self.vpnClient->start2connect(argc, argv, cfPass);
        BOOL result;
        if (ret!=0){
            result=false;
        }
        else {result = true;}
        completionHandler(result);
    }); 
}

Все они взяты из networkextension, и во время отладки я обнаружил, что int ret = self.vpnClient->start2connect(argc, argv, cfPass);, кажется, не возвращает никакого значения.

Однако я подтвердил, что start2connect метод возвращает значение int, так что на данный момент любой может помочь объяснить, что не так?

спасибо

1 Ответ

0 голосов
/ 30 мая 2019

BOOL * является указателем на BOOL.Мы не используем этот шаблон очень часто.Мы используем его там, где блок должен обновить свойство BOOL где-нибудь, например, в enumerateMatchesinString, где вы можете обновить логическое значение, на которое указывает stop, чтобы остановить перечисление.

Но это обработчик завершения, поэтому нет смысла передавать указатель на логическое значение (то, которое предположительно находилось в стеке, вызывая проблемы).Просто передайте сам логическое значение, а не указатель на него.

Я бы предложил вместо:

- (void)startTunnelWithOptions:(NSDictionary *)options completionHandler:(void (^)(BOOL * error))completionHandler {
    ...
    [vpnAdapter connect:host user:username pass:password add:YES completionHandler:^(BOOL success){
        completionHandler(&success);
    }];
    ...
}

Что вы хотите:

- (void)startTunnelWithOptions:(NSDictionary *)options completionHandler:(void (^)(BOOL success))completionHandler {
    ...
    [vpnAdapter connect:host user:username pass:password add:YES completionHandler:^(BOOL success){
        completionHandler(success);
    }];
    ...
}

Обратите внимание на блокпараметр не BOOL * error, а BOOL success, и когда он вызывает completionHandler, перед success не будет &.

Если есть какая-то причина, по которой вам нужно обновить BOOL,тогда это другой вопрос, но он не имеет смысла в контексте обработчика завершения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...