0

シンプルなパイプを使用しています。私はしばらくの間、一度に1文字ずつ読みます。文字を読み取るたびに、何かを上書きすると思います

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <string.h>

int main () {
    int pipefd[2];
    int cpid;
    char buf[31];
    if (pipe(pipefd) == -1) {
        perror("pipe");
        exit(EXIT_FAILURE);
    }
    cpid = fork();
    if (cpid == -1) {
        perror("cpid");
        exit(EXIT_FAILURE);
    }
    if (cpid == 0) {      // child reads from pipe
        close (pipefd[1]); // close unused write end
        int i = 0;
        while (read (pipefd[0], &(buf[i++]), 1)>0);
        printf ("Server receives: %s", buf);
        close (pipefd[0]);
        exit (EXIT_SUCCESS);
    }
    else {               // parent writes to pipe
        close (pipefd[0]); // closing unused read end;
        char buf2[30];
        printf("Server transmits: ");
        scanf ("%s", buf2);
        write (pipefd[1], buf2, strlen(buf2)+1);
        close(pipefd[1]);
        wait(NULL);
        exit(EXIT_SUCCESS);
    }
  return 0;
}

コードは修正されました。これは廃止されました:たとえば、「Flowers」と入力すると、F が出力され、その後 ~6 個の印刷不能文字が出力されます。

しかし、ちょっとした奇妙なことが起こっています.30よりも長い文字列を使用しただけで、エラーはまったく発生せず、文字列全体を書き込むことができました. 私の両方のバッファはそれよりもかなり小さいですが。

4

2 に答える 2

2

これは正しくありません:

while (read (pipefd[0], &buf, 1)>0);

バッファの最初の位置に文字を何度も読み込んでいます。代わりに、読み取り文字を置く位置をインクリメントする必要があります。

例えば

int i = 0;
while (read(pipefd[0], buf + i, 1) >0 ) ++i;
buf[i] = 0; // end string

buf サイズよりも大きくなっていないことを確認することもおそらく良いでしょう:

while (read(pipefd[0], buf + i, 1) >0 && i < sizeof(buf)) ++i;
于 2012-06-08T04:41:47.597 に答える
1

(アンダースの提案に従います。)

GCC 4.6.3 を使用して、私のコード:

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <string.h>

int main () {
    int pipefd[2];
    int cpid;
    char buf[31];
    if (pipe(pipefd) == -1) {
        perror("pipe");
        exit(EXIT_FAILURE);
    }
    cpid = fork();
    if (cpid == -1)
    {
        perror("cpid");
        exit(EXIT_FAILURE);
    }
    if (cpid == 0) {      // child reads from pipe
        close (pipefd[1]); // close unused write end
        int i=0;
        while (read(pipefd[0], &(buf[i++]), 1) != 0);
        printf ("Server receives: %s\n", buf);
        close (pipefd[0]);
        exit (EXIT_SUCCESS);
    }
    else {               // parent writes to pipe
        close (pipefd[0]); // closing unused read end;
        char buf2[30];
        printf("Server transmits: ");
        scanf ("%s", buf2);
        write (pipefd[1], buf2, strlen(buf2)+1);
        close(pipefd[1]);
        wait(NULL);
        exit(EXIT_SUCCESS);
    }
  return 0;
}

プロデュース:

[user@host tmp]$ gcc pipes.c -o pipes && ./pipes 
Server transmits: Flowers
Server receives: Flowers

(境界チェックに関する彼の意見にも同意します。)


編集:あなたのコメントに従って、次の行を変更した場合(私にとっては35)

scanf("%s", buf2);

fgets(buf2, 30, stdin);

あなたは2つの利益を得る。(a) にコピーされるバイト数を制限することで、バッファ オーバーフローの脆弱性を排除しますbuf2。(b)改行以外の空白(スペースとタブ)を「受け入れる」ことができますscanfが、 では次のことができませんでした:

[user@host tmp]$ gcc pipes.c -o pipes && ./pipes 
Server transmits: Flowers smell nice
Server receives: Flowers smell nice
于 2012-06-08T05:01:34.137 に答える