3

I'm working on a C program to solve the Dining Philosophers' problem. I loop through 500 philosopher state changes, and output each philosophers' status on each interation with the following statement:

printf("  %d> |%s|%s|%s|%s|%s \n", i, get_state(phils[0]), get_state(phils[1]), get_state(phils[2]), get_state(phils[3]), get_state(phils[4]));

For context, here is the function get_state, which converts a numeric philosopher status into a string:

char * get_state(int t) {
    if (t == 1)
        return "  Thinking   ";
    if (t == 2)
        return "   Hungry    ";
    if (t == 3)
        return "   Eating    ";
    return "----Error----";
}

My problem is this: every 5-30 lines, one of them will start with the unicode character U+0001. It appears that it is probably being inserted after the \n of the previous line, but I can't tell what causes it at all!

I've provided a screenshot for clarity: enter image description here

And here is the whole loop:

for (i = 1; i <= MAX; i++) {
    silent = 0;
    // receive message from child node
    for (j = 0; j < PHIL_NO; j++) {
        if(phils[j] == EATING) {
            count[j]++;
        }
        lastPhils[j] = phils[j];
    };
    read(host[READ], &msg, sizeof(msg));
    phils[msg.index] = msg.state;


    for (j = 0; j < PHIL_NO; j++) {
        if (phils[j] == lastPhils[j]) 
        {
            silent++;
        }
    };

    printf("%4d> |%s|%s|%s|%s|%s \n", i, get_state(phils[0]), get_state(phils[1]),
            get_state(phils[2]), get_state(phils[3]), get_state(phils[4]));


    // if message is "hungry"
    if (msg.state == HUNGRY) {
        state_left = 0;
        state_right = 0;
        // check if chopsticks are available

        if (phils[(msg.index - 1)%PHIL_NO] == EATING) {
            state_left = 1;
        }

        if(phils[(msg.index + 1)%PHIL_NO] == EATING) {
            state_right = 1;
        }
        // if available...
        if (state_left+state_right == 0) {
            // send message EATING to node
            msg.state = EATING;
            write(node[msg.index][WRITE], &msg, sizeof(msg));
        } else {
            // make the node wait
            write(node[msg.index][WRITE], &msg, sizeof(msg));
        }
    } else if (msg.state == THINKING) {
        // awake neighborhood nodes to eat
        write(node[(msg.index-1)%PHIL_NO][WRITE], &msg, sizeof(msg));
        write(node[(msg.index+1)%PHIL_NO][WRITE], &msg, sizeof(msg));

    }
};

Edit: Oddly enough, when I run it in XTerm I can't see the extra character. I think that just means that XTerm doesn't display it. At this point, I'm pretty sure @Barmar is right in assuming it's one of my pipe write()s misbehaving.

Dakota B
  • 138
  • 9
  • 3
    I don't see anything in the code you posted that would account for this, and there isn't enough information to reproduce the problem. Is there any place else in your program that could be calling `printf` or `putchar` or something similar? – Tom Karzes Oct 23 '18 at 00:31
  • 3
    Please post the whole loop. I agree that the code you posted can't be the cause by itself. – Barmar Oct 23 '18 at 00:32
  • I'm confused by your screenshot. I think with `%s` your strings should be right justified, but it looks like your strings are centered between the vertical bars. What sorcery is this? – bruceg Oct 23 '18 at 00:37
  • 2
    I've posted the whole loop for any extra context it may bring. The strings are centered because I space-padded them in the `get_state` function. – Dakota B Oct 23 '18 at 00:40
  • 2
    I suspect one of those `write()` calls later in the function is doing it. I'll bet you're accessing outside the `node` array and getting `1` as the value of `node[msg.index][WRITE]` – Barmar Oct 23 '18 at 00:50
  • 2
    Run your program under a debugger, and single-step through the code with all the `write()` calls, you'll probably find it. – Barmar Oct 23 '18 at 00:52
  • @davedwards He's not printing anything from a variable that was scraped anywhere. – Barmar Oct 23 '18 at 00:52
  • 1
    @DakotaB You might wanna try suppressing stderr when you run your program "a.out 2>nul" or something along those lines. it could be read or write is erroring or something behind the scenes is erroring, and sending something to stderr. Check the return values of read/write, and fflulsh stdout or stderr to test this hypothesis. Whatever is doing it, it looks like its not stdout. – Bwebb Oct 23 '18 at 00:56
  • I think @Barmar is right. You can make a wrapper around the `write`, call and detect when the `fd` you specify is stdout or stderr. – bruceg Oct 23 '18 at 01:44
  • 1
    Break the habit of putting semicolons after the `}` that marks the end of a `for` loop (or a `while` loop) now. It marks the end of an empty statement that does nothing useful. – Jonathan Leffler Oct 23 '18 at 05:44
  • Did you ever figure this out? – Barmar Nov 05 '18 at 19:57

0 Answers0