Цель c получает ошибку EXC_BAD_ACCESS при завершении обработчика

я новичок в 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 так что на данный момент кто-нибудь может помочь объяснить, что не так?

Спасибо

Почему параметр блока для startTunnelWithOptions использует BOOL *? Почему бы просто не сделать его параметр BOOL тоже? Тогда вы просто делаете completionHandler(success); и все готово. Я не понимаю, что вы пытаетесь сделать...

Rob 30.05.2019 05:56

Вы можете быть более конкретным? Спасибо

ikel 30.05.2019 06:44

Кстати, когда вы запустите это, я бы посоветовал вам запустить это через инструмент «Утечки» в «Инструментах», потому что все эти malloc вызовы без соответствующих free вызовов должны вызывать утечки.

Rob 30.05.2019 07:11
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
3
84
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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, то это другое дело, но в контексте обработчика завершения это не имеет смысла.

Другие вопросы по теме