Der folgende Code ist eine Signal Implementierung, die mit einer kleinen Änderung aus APUE kopiert wurde
%Vor%Der obige Code funktioniert gut während meines Tests, aber ich wollte es eher wie einen C ++ - Code machen, also habe ich den Alias von signal_handler in
geändert %Vor%und auch ich benutze
%Vor%ersetzen
%Vor%und jetzt gibt es ein Problem. Ich finde newAction.sa_handler ist immer noch NULL nach
%Vor%aber ich weiß nicht warum. Kann mir jemand helfen, das zu erklären? Vielen Dank. Hier ist mein Testcode:
%Vor%Auch wenn ich den Originalcode verwende, wenn ich ihn in Xcode laufe, gibt es keine Ausgabe. Stattdessen führe ich die ausführbare Datei manuell aus, ich kann SIGUSR1 passiert im Terminal sehen. Warum? Wie kann ich die Ausgabe mit Xcode sehen?
Die direkte Antwort ist, dass target()
sehr wählerisch ist - Sie müssen es nennen der Typ des Ziels genau , um einen Zeiger darauf zu erhalten, andernfalls erhalten Sie einen Nullzeiger. Wenn Sie Ihr Signal auf usr1_handler
setzen, ist das ein -Zeiger für eine Funktion (keine Funktion) - sein Typ ist void(*)(int)
, nicht void(int)
. Du gibst also target()
einfach den falschen Typ. Wenn Sie ändern:
bis
%Vor%das würde Ihnen das richtige Ziel geben.
Beachten Sie jedoch, was target()
tatsächlich zurückgibt:
Es gibt einen Zeiger auf den angegebenen Typ zurück - in diesem Fall wäre das ein void(**)(int)
. Sie müssen dies vor der weiteren Zuweisung dereferenzieren. Etwas wie:
Demo .
Die wirkliche Antwort ist jedoch, dass dies wenig Sinn macht. std::function<Sig>
ist ein gelöschter Typ, der für die angegebene Sig
aufgerufen werden kann - es kann ein Zeiger auf eine Funktion, ein Zeiger auf eine Elementfunktion oder sogar ein umgebendes Funktionsobjekt beliebiger Größe sein. Es ist eine sehr generische Lösung. Aber sigaction
akzeptiert nicht irgendeine Art von generischer Callable - sie akzeptiert spezifisch a void(*)(int)
.
Durch Erstellen einer Signatur von:
%Vor%Sie schaffen die Illusion, dass Sie alle aufrufbaren erlauben! Also könnte ich versuchen, etwas wie:
zu übergeben %Vor% Das ist erlaubt durch Ihre Unterschrift - Ich biete eine aufrufbar an, die ein int
benötigt. Aber das Callable ist nicht in einen Funktionszeiger umwandelbar, also ist es nicht etwas, das du an sigaction()
weitergeben kannst, also ist das nur ein fehlerhafter Code, der nie funktionieren kann - das ist ein garantierter Laufzeitfehler.
Noch schlimmer, ich könnte etwas übergeben, das in einen Funktionszeiger umgewandelt werden kann, aber vielleicht weiß ich nicht, dass es das ist, was Sie brauchen, also gebe ich Ihnen das Falsche:
%Vor% Da sigaction()
Sie auf Funktionszeiger beschränkt, sollten Sie Ihre Schnittstelle auf Funktionszeiger beschränken. Stark bevorzugen, was Sie vorher hatten. Verwenden Sie das Typsystem, um Fehler abzufangen - verwenden Sie nur Typlöschung, wenn es sinnvoll ist.