C 段错误(Libcapn APNS 库)

标签 c segmentation-fault apple-push-notifications

我正在开发一个 C 程序,它使用 Libcapn 库 ( http://libcapn.org ) 连接到 Apple 的推送通知服务并发送推送通知。

网站上显示的示例运行良好,我可以用它向我的 iPhone 发送推送通知。

现在我打算将其集成到我现有的程序中,以向我的 iPhone 发送更具体的通知,但当我尝试将代码拆分为多个函数时,我总是遇到段错误。

示例:在给定的代码中,一切都发生在 main 函数中:

int main() {
    apn_payload_t *payload = NULL;
    apn_ctx_t *ctx = NULL;
    time_t time_now = 0;
    char *invalid_token = NULL;

    // ...

    if(NULL == (ctx = apn_init())) {
        printf("Unable to init context: %d\n", errno);
        apn_library_free();
        return -1;
    }

    apn_set_pkcs12_file(ctx, "my-certificate.p12", "my4711passphrase");
    apn_set_mode(ctx,  APN_MODE_SANDBOX); //APN_MODE_PRODUCTION or APN_MODE_SANDBOX
    apn_set_behavior(ctx, APN_OPTION_RECONNECT);
    apn_set_log_level(ctx, APN_LOG_LEVEL_INFO | APN_LOG_LEVEL_ERROR | APN_LOG_LEVEL_DEBUG);
    apn_set_log_callback(ctx, __apn_logging);
    apn_set_invalid_token_callback(ctx, __apn_invalid_token);

    // ...

}

虽然它有效,但并不完全是我想要的。我不想每次想发送单个通知时都分配/释放所有资源。因此我想在启动时打开连接,将模式设置为“RECONNECT”(这样它会在连接关闭后自动重新连接),并在程序终止时释放所有资源。

所以,如果我只是“外包”,例如将上下文初始化为新函数时,出现段错误。这是我所做的:

int apn_ctx_init_wrapper(apn_ctx_t *ctx) {
    if(NULL == (ctx = apn_init())) {
        printf("Unable to init context: %d\n", errno);
        apn_library_free();
        return -1;
    }

    apn_set_pkcs12_file(ctx, "my-certificate.p12", "my4711passphrase");
    apn_set_mode(ctx,  APN_MODE_SANDBOX); //APN_MODE_PRODUCTION or APN_MODE_SANDBOX
    apn_set_behavior(ctx, APN_OPTION_RECONNECT);
    apn_set_log_level(ctx, APN_LOG_LEVEL_INFO | APN_LOG_LEVEL_ERROR | APN_LOG_LEVEL_DEBUG);
    apn_set_log_callback(ctx, __apn_logging);
    apn_set_invalid_token_callback(ctx, __apn_invalid_token);

    return 0;
}

...我将上面的代码替换为单个函数调用,例如 apn_ctx_init_wrapper(ctx);。它甚至不返回 0-1。当调用函数 get 时,出现段错误。为什么?请帮助我!

最佳答案

这是按值传递指针并尝试将指针的本地副本指向新位置的经典案例。原始指针仍指向原始位置。

我将为您提供两种解决这种情况的方法。

您可以修改该函数,使其接受指针的地址。

int apn_ctx_init_wrapper(apn_ctx_t **ctx) {
    if(NULL == (*ctx = apn_init())) { //Note that the pointer needs to be dereferenced
        printf("Unable to init context: %d\n", errno);
        apn_library_free();
        return -1;
    }

    apn_set_pkcs12_file(*ctx, "my-certificate.p12", "my4711passphrase");
    apn_set_mode(*ctx,  APN_MODE_SANDBOX); //APN_MODE_PRODUCTION or APN_MODE_SANDBOX
    apn_set_behavior(*ctx, APN_OPTION_RECONNECT);
    apn_set_log_level(*ctx, APN_LOG_LEVEL_INFO | APN_LOG_LEVEL_ERROR | APN_LOG_LEVEL_DEBUG);
    apn_set_log_callback(*ctx, __apn_logging);
    apn_set_invalid_token_callback(*ctx, __apn_invalid_token);

    return 0;
}

在 main 中,您可以将其称为 if(apn_ctx_init_wrapper(&ctx) != -1)

第二种方法是返回上下文,而不是返回 0-1

apn_ctx_t *apn_ctx_init_wrapper() {
    apn_ctx_t *ctx;
    if(NULL == (ctx = apn_init())) {
        printf("Unable to init context: %d\n", errno);
        apn_library_free();
        return NULL;
    }

    apn_set_pkcs12_file(ctx, "my-certificate.p12", "my4711passphrase");
    apn_set_mode(ctx,  APN_MODE_SANDBOX); //APN_MODE_PRODUCTION or APN_MODE_SANDBOX
    apn_set_behavior(ctx, APN_OPTION_RECONNECT);
    apn_set_log_level(ctx, APN_LOG_LEVEL_INFO | APN_LOG_LEVEL_ERROR | APN_LOG_LEVEL_DEBUG);
apn_set_log_callback(ctx, __apn_logging);
apn_set_invalid_token_callback(ctx, __apn_invalid_token);

    return ctx;
}

在 main 中,您可以将其称为 if(NULL == (ctx = apn_ctx_init_wrapper()))。当函数创建和初始化上下文时,无需将上下文传递给函数。

我更喜欢第二种方法。

关于C 段错误(Libcapn APNS 库),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38755132/

相关文章:

c - 将一个结构中的信息存储到另一个结构中

C段错误,不确定发生了什么

ios - 如何将 Iphone 的远程通知传递给 Watch OS?

php - 重复的 Apple APNS 推送通知?

c - 使用 execvp 连接标准输入吗?

c - 如何在C中交换双向链表中的两个相邻项

C:当指针实际上指向某物时,函数不断接收归零指针

c - 强制转换 void 指针地址的含义

ios - 收到推送消息时从 Appdelegate 导航

c++ - 在 X 个字符后限制 libcurl 返回