Ich arbeite an einem C-Programm, das die Bibliothek Libcapn (http://libcapn.org) verwendet, um eine Verbindung zu Push-Benachrichtigungsdienst von Apple herzustellen und Push-Benachrichtigungen zu senden.C Segmentation Fault (Libcapn APNS-Bibliothek)
Das Beispiel, das auf der Website gezeigt wird, funktioniert gut, ich kann damit Push-Benachrichtigungen an mein iPhone senden.
Jetzt werde ich dies in mein bestehendes Programm integrieren, um spezifischere Benachrichtigungen an mein iPhone zu senden, aber ich bekomme immer einen Segmentierungsfehler, wenn ich versuche, den Code in mehrere Funktionen aufzuteilen.
Beispiel: In dem gegebenen Code alles in der main
Funktion geschieht:
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);
// ...
}
Obwohl es funktioniert es ist nicht genau das, was ich will. Ich möchte nicht alle Ressourcen zuweisen/freigeben, wenn ich eine einzige Benachrichtigung senden möchte. Daher möchte ich die Verbindung beim Start öffnen, den Modus auf "RECONNECT" setzen (damit sie sich automatisch wieder verbindet, nachdem die Verbindung geschlossen wurde) und einfach alle Ressourcen freigeben, wenn das Programm beendet wird.
Also wenn ich nur z. die Initialisierung der context
zu einer neuen Funktion, bekomme ich einen Segmentierungsfehler. Hier ist, was ich getan habe:
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;
}
... und ich ersetzt den Code oben mit zu einem einzigen Funktionsaufruf wie apn_ctx_init_wrapper(ctx);
. Es gibt nicht einmal 0
oder -1
. Wenn die Funktion get aufgerufen wird, bekomme ich einen segfault. Warum? Bitte hilf mir!
Da gibt es eine c-Routine namens 'connect()'. Während Sie Ihren Code nicht direkt gegen 'connect()' aufrufen oder kompilieren, wird 'apn_connect()' dies tun. Versuchen Sie, einen anderen Namen zu verwenden, der nicht mit einem vorhandenen Konflikt in Konflikt steht. Ich schlage 'apn_connect_wrapper()' vor, damit Sie und zukünftiger Maintainer sich daran erinnern, dass es nur ein Wrapper für die 'apn_connect()' ist. – alvits
Sie haben Recht. Der Name wurde geändert und es funktioniert. Aber wenn ich einen anderen Code auslagere, bekomme ich immer noch einen segfault. Ich aktualisiere meine Frage. – beeef
Diese 'ctx = apn_init()' setzt 'ctx' auf die von' apn_init() 'zurückgegebene Adresse. Das Problem ist, dass Sie die dynamisch zugewiesene Adresse verlieren, wenn 'apn_ctx_init_wrapper()' zum Aufrufer zurückkehrt.Denken Sie daran, dass Sie den Wert von 'ctx' aus' main() 'übergeben und in' apn_ctx_init_wrapper() 'Sie dachten, Sie ersetzen den Inhalt von' ctx', aber Sie sind nicht, weil Sie den Wert überschritten haben. Im späteren Teil Ihres Codes, wenn Sie 'ctx' referenzieren, enthält er immer noch den Anfangswert, den er vor dem Aufruf von' apn_ctx_init_wrapper() 'hatte. Ändern Sie den Wrapper, um 'apn_ctx_t ** ctx' zu akzeptieren. – alvits