簡體   English   中英

從標准輸入連續讀取

[英]Reading continuously from stdin

我剛開始學習 C,如果我錯過了一些明顯的東西,我很抱歉。 作為一種實踐,我想編寫自己的 posix cat ,並且幾乎可以正常工作,但是當沒有 arguments 時,它不會從 stdin 讀取多個文件。

這是預期的行為(忽略這一點,因為這是我不知道的 Zsh 功能):

$ cat < hello.txt < world.txt
hello
world
$ 

但是我的cat因“分段錯誤”而崩潰(我有一個沒有崩潰的版本,但它也沒有 output 任何東西)

這是代碼:

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>

int main(int argc, char *argv[])
{
    char opt;
    while ((opt = getopt(argc, argv, "u")) != EOF) {
        switch(opt) {
            case 'u':
                /* Make the output un-buffered */
                setbuf(stdout, NULL);
                break;
            default:
                break;
        }
    }

    argc -= optind;
    argv += optind;

    int i = 0, fildes, fs = 0;

    do {
        /* Check for operands, if none or operand = "-". Read from stdin */
        if (argc == 0 || !strcmp(argv[i], "-")) {
            fildes = STDIN_FILENO;
        } else {
            fildes = open(argv[i], O_RDONLY);
        }

        /* Check for directories */
        struct stat fb;
        if (!fstat(fildes, &fb) && S_ISDIR(fb.st_mode)) {
            fprintf(stderr, "cat: %s: Is a directory\n", argv[i]);
            i++;
            continue;
        }

        /* Get file size */
        fs = fb.st_size;

        /* If bytes are read, write them to stdout */
        char buf[fs];
        while ((read(fildes, buf, fs)) > 0)
            write(STDOUT_FILENO, buf, fs);

        /* Close file if it's not stdin */
        if (fildes != STDIN_FILENO)
            close(fildes);

        i++;
    } while (argv[i] != NULL || argc == 0);

    return 0;
}

當您使用帶有-fsanitize=address的 gcc 編譯代碼時,代碼顯示:

AddressSanitizer:DEADLYSIGNAL
=================================================================
==604950==ERROR: AddressSanitizer: stack-overflow on address 0x7ffea6d94000 (pc 0x55b9a63dfb57 bp 0x7ffea6d90d20 sp 0x7ffea6d90b80 T0)
    #0 0x55b9a63dfb57 in main /tmp/10/1.c:56
    #1 0x7f1403c17b24 in __libc_start_main (/usr/lib/libc.so.6+0x27b24)
    #2 0x55b9a63df3dd in _start (/tmp/.ccrun.604893.exefile+0x23dd)

SUMMARY: AddressSanitizer: stack-overflow /tmp/10/1.c:56 in main
==604950==ABORTING

片段:

do {
   ...
   ++i;
} while (argv[i] != NULL || argc == 0);       // HERE!

argc始終為0 ,因此while(...)始終在執行,而++i始終在遞增。 argc[...]被越界訪問,直到出現段錯誤。

我認為您應該將其更改為} while (argv[i];= NULL && argc != 0);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM