0

I need to print out a string along with a integer in a signal handler function. I was told that write is signal safe. So far I have tried to print out an integer with write but it gives off weird symbols. Write worked for a char array of characters but doesn't work for integers. Any advice would be much appreciated. Below is my code which gave off the error.

    #include<stdio.h> 
    #include<wait.h> 
    #include<signal.h> 
    #include<unistd.h>
    int main() 
    { 
        int x[] = {100000};
        write(1, x, sizeof(x));
        return 0;
    }
Shiro Pie
  • 213
  • 1
  • 8
  • 2
    What are you expecting to get written? –  Feb 26 '19 at 23:41
  • 1
    If you don't understand the relationship between your array contents and the file, look at the file -- and your memory -- with a hex editor. Memory contents aren't encoded in ASCII (absent an effort to make it so), so you can't expect a textual representation when you dump them directly to disk. – Charles Duffy Feb 26 '19 at 23:42
  • I just write to print the integer to the console. – Shiro Pie Feb 26 '19 at 23:45
  • 100000 is 000186a0 in hex. So the bytes are 00, 01, 86, a0. If your machine is little-endian, then they will come out as a0, 86, 01, 00. The first two characters are non-ascii. What exactly are you expecting? If you want to see a textual representation of your integer, then you first need to convert it to a printable string. – Tom Karzes Feb 26 '19 at 23:48
  • 1
    `write` prints raw bytes, and the raw bytes of 100000 aren't the same as the raw bytes of the string "100000". Even though write is async-signal-safe, it doesn't fit your other important requirement that you print an integer as a string. – zneak Feb 26 '19 at 23:48
  • Maybe convert the integer into an array of characters? – David Schwartz Feb 26 '19 at 23:51
  • Just for reference, there's list of signal safe functions [here](http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_04_03). – John Szakmeister Feb 26 '19 at 23:58

2 Answers2

1

When I compile your program and redirect the output through hexdump, this is the output I get:

$ gcc t.c
$ ./a.out | hexdump
0000000 86a0 0001
0000004
$

Then, we note that 100000 in hexadecimal is 0x186a0. What your program does is emit the raw bytes for the object that represents the number 100000.

If you want to print the number 100000 to the output in ASCII, you can write your own routine for doing so. For example:

void
print_number(unsigned x) {
    if (x >= 10) print_number(x/10);
    write(1, "0123456789" + (x%10), 1);
}

A better way would be to emit the converted characters into a buffer, and use a single write call on the buffer text that now holds the string version of the number.

jxh
  • 69,070
  • 8
  • 110
  • 193
1

Here are the bytes that make up the integer 100000 in memory, that I've converted to hexadecimal:

A0 86 01 00

Here are the bytes that write(1, x, sizeof(x)) prints, in hexadecimal:

A0 86 01 00

Here are the bytes that printf("%d", x[0]) prints, in hexadecimal:

31 30 30 30 30 30

31 (hexadecimal) is the ASCII code for the digit 1 and 30 is for the digit 0. But A0, 87, 01 and 00 are strange symbols. When you use printf it converts the number into something designed for humans to read; write does not such conversion.

To print numbers to the console in a way that can be understood by people, use printf. But you shouldn't use printf inside a signal handler, you say - that's correct, because you shouldn't write to the console inside a signal handler. (Would it be okay if your signal handler writes in the middle of a different write?)

If this is just a test, calling printf in the signal handler might be good enough, but every now-and-again it'll crash, so don't do that in programs that you give to other people.

user253751
  • 57,427
  • 7
  • 48
  • 90
  • Thank you for the advice. But I sorta have to use write() inside a signal handler and its not optional.This is just one part of my project. Is there any advice on how to fix this? – Shiro Pie Feb 26 '19 at 23:55
  • Use a different function to convert the number into decimal digits first. Such as snprintf. But I'm not sure if snprintf can be used inside a signal handler either. – user253751 Feb 27 '19 at 00:46