简体   繁体   中英

How to fix a pipe in C++

I am still a novice when it comes to UNIX and C++, creating a sort of unruly mess.

My task is to create a pipe, fork the process, let the parent process read in characters from a text file, pass those characters through the pipe to the child process, have the child process convert the case of the character from uppercase to lowercase or vice versa, then output the character.

When I run this code I see the following error: (null) Segmentation Fault (Core Dumped)

When I put sleeper print statements into the program, I saw that the program located the file, forked properly, but while the child process began, the parent wouldn't start. Any help is greatly appreciated.

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>

int main()
{

    FILE* fh;
    fh = fopen("data.txt", "r");
    int pipeID[2];
    pipe(pipeID);
    int len;

    if (fork() == 0) //this is the filter process
    {
        char filter[len];
        read(pipeID[0], filter, len);
        if (filter[0] >= 'a' && filter[0] <= 'z')
            filter[0] = filter[0] - 32;
        else if (filter[0] >= 'A' && filter[0] <= 'Z')
            filter[0] = filter[0] + 32;
        printf("%s", filter[0]);
    }

    else {
        char ch;
        char* toFilter;
        for (ch = getc(fh); ch != EOF; ch = getc(fh)) {
            printf("%s", ch);
            write(pipeID[1], &ch, len);
        }
    }
}

Why are you printing characters and using string specifiers? You are probably accessing some not allowed memory locations.. Try using %c instead of %s.

I see one major problem with several other glitches. Based on your code, I modified like this (still not good), and please see comments prefacing #<num> :

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>

int main()
{
    FILE* fh;
    fh = fopen("data.txt", "r");
    int pipeID[2];
    pipe(pipeID);
    /* int len; */  // #1 `len` is not needed

    if (fork() == 0)
    {
        close(pipeID[1]); // #2-1 usually we close unused end of pipe
        char filter[1024];
        int read_len;
        while ((read_len = read(pipeID[0], filter, sizeof(filter))) > 0) // #3 see below
        {
            for (int i = 0; i < read_len; ++i)
            {
                if (filter[i] >= 'a' && filter[i] <= 'z')
                    filter[i] = filter[i] - 32;
                else if (filter[i] >= 'A' && filter[i] <= 'Z')
                    filter[i] = filter[i] + 32;

                printf("%c", filter[i]);
            }
        }
    }
    else {
        close(pipeID[0]); // #2-2 same as #2-1
        char ch;
        /* char* toFilter; */ // #4 remove unused variable
        while ((ch = getc(fh)) != EOF) { // #5 a while is better than for
            printf("%c", ch);   // #6 %s -> %c
            write(pipeID[1], &ch, sizeof(char)); // #7 len -> sizeof(char)
        }
    }
}

The biggest problem is in the #3 part. You may think once you write to a pipe, the other end of pipe will immediately read the data. However, you can't rely on exactly one char is written and then read. So you need read as much as possible alternately until an EOF indicating the end of writing. Therefore, I changed the code as #3.

As for other problems, they are not really faulty. I think these are caused by carelessness.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM