Terapkan async-signal-safe Anda sendiri snprintf("%d
dan gunakanwrite
Ini tidak seburuk yang saya pikirkan, Bagaimana cara mengubah int menjadi string di C? memiliki beberapa implementasi.
Karena hanya ada dua jenis data yang menarik yang dapat diakses oleh penangan sinyal:
sig_atomic_t
global
int
argumen sinyal
ini pada dasarnya mencakup semua kasus penggunaan yang menarik.
Fakta bahwa strcpy
sinyal juga aman membuat segalanya menjadi lebih baik.
Program POSIX di bawah ini mencetak berapa kali ia menerima SIGINT sejauh ini, yang dapat Anda picu dengan Ctrl + C
, dan ID sinyal.
Anda dapat keluar dari program dengan Ctrl + \
(SIGQUIT).
main.c:
#define _XOPEN_SOURCE 700
#include <assert.h>
#include <limits.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#define ITOA_SAFE_STRLEN(type) sizeof(type) * CHAR_BIT + 2
char *itoa_safe(intmax_t value, char *result, int base) {
intmax_t tmp_value;
char *ptr, *ptr2, tmp_char;
if (base < 2 || base > 36) {
return NULL;
}
ptr = result;
do {
tmp_value = value;
value /= base;
*ptr++ = "ZYXWVUTSRQPONMLKJIHGFEDCBA9876543210123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[35 + (tmp_value - value * base)];
} while (value);
if (tmp_value < 0)
*ptr++ = '-';
ptr2 = result;
result = ptr;
*ptr-- = '\0';
while (ptr2 < ptr) {
tmp_char = *ptr;
*ptr--= *ptr2;
*ptr2++ = tmp_char;
}
return result;
}
volatile sig_atomic_t global = 0;
void signal_handler(int sig) {
char key_str[] = "count, sigid: ";
char buf[2 * ITOA_SAFE_STRLEN(sig_atomic_t) + sizeof(key_str)];
enum { base = 10 };
char *end;
end = buf;
strcpy(end, key_str);
end += sizeof(key_str);
end = itoa_safe(global, end, base);
*end++ = ' ';
end = itoa_safe(sig, end, base);
*end++ = '\n';
write(STDOUT_FILENO, buf, end - buf);
global += 1;
signal(sig, signal_handler);
}
int main(int argc, char **argv) {
{
typedef struct {
intmax_t n;
int base;
char out[1024];
} InOut;
char result[1024];
size_t i;
InOut io;
InOut ios[] = {
{0, 10, "0"},
{1, 10, "1"},
{9, 10, "9"},
{10, 10, "10"},
{100, 10, "100"},
{-1, 10, "-1"},
{-9, 10, "-9"},
{-10, 10, "-10"},
{-100, 10, "-100"},
{0, 2, "0"},
{1, 2, "1"},
{10, 2, "1010"},
{100, 2, "1100100"},
{-1, 2, "-1"},
{-100, 2, "-1100100"},
{0, 35, "0"},
{1, 35, "1"},
{34, 35, "Y"},
{35, 35, "10"},
{100, 35, "2U"},
{-1, 35, "-1"},
{-34, 35, "-Y"},
{-35, 35, "-10"},
{-100, 35, "-2U"},
};
for (i = 0; i < sizeof(ios)/sizeof(ios[0]); ++i) {
io = ios[i];
itoa_safe(io.n, result, io.base);
if (strcmp(result, io.out)) {
printf("%ju %d %s\n", io.n, io.base, io.out);
assert(0);
}
}
}
if (argc > 1 && !strcmp(argv[1], "1")) {
signal(SIGINT, signal_handler);
while(1);
}
return EXIT_SUCCESS;
}
Kompilasi dan jalankan:
gcc -std=c99 -Wall -Wextra -o main main.c
./main 1
Setelah menekan Ctrl + C lima belas kali, terminal menunjukkan:
^Ccount, sigid: 0 2
^Ccount, sigid: 1 2
^Ccount, sigid: 2 2
^Ccount, sigid: 3 2
^Ccount, sigid: 4 2
^Ccount, sigid: 5 2
^Ccount, sigid: 6 2
^Ccount, sigid: 7 2
^Ccount, sigid: 8 2
^Ccount, sigid: 9 2
^Ccount, sigid: 10 2
^Ccount, sigid: 11 2
^Ccount, sigid: 12 2
^Ccount, sigid: 13 2
^Ccount, sigid: 14 2
dimana 2
nomor sinyal untuk SIGINT
.
Diuji di Ubuntu 18.04. GitHub upstream .
printf
panggilan itu di penangan sinyal itu? Hapus.