使用 C 的 getline() 时的奇怪行为

Posted

技术标签:

【中文标题】使用 C 的 getline() 时的奇怪行为【英文标题】:Strange behavior while using C's getline() 【发布时间】:2016-08-20 13:45:47 【问题描述】:

我在编写一个小的 c 程序时,在 getline 函数中遇到了一些奇怪的行为。我想做什么:

    stdout 重定向到文件 将stderr 重定向到文件 将stdin 重定向到文件 将stdin逐行读入字符串数组(char *path_array) 打印输出

现在,当我运行程序时,输出如下所示:

retrieving line of size 73.
line1 llllllllllllskdjflaksdlfkalskdddddddffffffffffffffffffffffffffffff

retrieving line of size 6.
line2

retrieving line of size 6.
line3

retrieving line of size 6.
line4

retrieving line of size 6.
line5

retrieving line of size 6.
line6

retrieving line of size 6.
line7

retrieving line of size 6.
line8

retrieving line of size 1.


retrieving line of size 13.
sdkfjlskdfos

retrieving line of size 9.
sldjflsd

retrieving line of size 9.
sdlfkjsd

retrieving line of size 11.
2222222222

retrieving line of size 11.
3333333333




retrieving line from array: 



retrieving line from array: 



retrieving line from array: 



retrieving line from array: 



retrieving line from array: 



retrieving line from array: 



retrieving line from array: 



retrieving line from array: 



retrieving line from array: 



retrieving line from array: 



retrieving line from array: 



retrieving line from array: 



retrieving line from array: 



retrieving line from array: 

在此输出的末尾,每个retrieving line from array 下方,应该有来自数组的相应字符串。如您所见,数组中填充了空字符串。

使用 Clion 的调试模式,我发现了为什么会这样:

在第一个for 循环中,每个数组条目都被当前的line 填充。所以不是

path_array[0] = line1

path_array[1] = line2

path_array[3] = line3...

去吧

path_array[0] = line1

path_array[0] = line2, path_array[1] = line2

path_array[0] = line3, path_array[1] = line3, path_array[2] = line3...

为什么会这样?我该如何阻止这种情况发生?

这是 C 代码:

#include <zconf.h>
#include <dirent.h>
#include <stdlib.h>
#include <fcntl.h>
#include <stdio.h>

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wmissing-noreturn"
int main(void) 

    int out_log;
    int err_log;
    int conf_in;

    pid_t pid = fork();

    DIR *dir;
    struct dirent *entry;

    //for getline()
    char *line = NULL;
    size_t len = 0;
    ssize_t read;

    int array_size = 0;

//    if (pid < 0) 
//        exit(1);
//    
//    else if (pid > 0) 
//        exit(0);
//    
//
//    if (setsid() <= 0) 
//        exit(1);
//    

    if (chdir("/") != 0) 
        exit(1);
    

//    if ((dir = opendir(".")) == NULL) 
//        exit(1);
//    

    //redicrect stdout
    if (dup2(out_log = open("PATH_TO_OUT_FILE", O_WRONLY | O_TRUNC), 1) != 1) 
        exit(1);
    
    if (close(out_log) != 0) 
        exit(1);
    

    //redirect stderr
    if (dup2(err_log = open("PATH_TO_ERR_FILE", O_WRONLY | O_TRUNC), 2) != 2) 
        exit(1);
    
    if (close(err_log) != 0) 
        exit(1);
    

    //redirect stdin
    if (dup2(conf_in = open("PATH_TO_IN_FILE", O_RDONLY), 0) < 0) 
        exit(1);
    
    if (close(conf_in) != 0) 
        exit(1);
    

    while ((read = getline(&line, &len, stdin)) != -1) 
        array_size++;

        printf("retrieving line of size %zd.\n", read);

        printf("%s\n", line);
    

    rewind(stdin);

    char *path_array[array_size];

    for (int i = 0; i < array_size; i++) 
        getline(&line, &len, stdin);

        // HERE IS WHERE IT GOES WRONG
        path_array[i] = line;
    

    free(line);

    for (int i = 0; i < array_size; i++) 
        printf("\n\n\nretrieving line from array: %s\n", path_array[i]);
    

//    while (1) 
//        puts("test output");
//        printf("%zd\n", read);
//
//        fflush(stdout);
//
//        sleep(1);
//    

#pragma clang diagnostic pop

【问题讨论】:

1) getline 不是标准的 C 函数,而是 POSIX 2) 不要支持没有必要的警告。添加return,函数无论如何都会返回一个值! 3) char *path_array 是指向char 的指针,不是数组,less 不能指向chararrays。 4) TL;DR,提供minimal reproducible example 并使用调试器。 @alk 它将成为一个守护进程。出于调试目的,我注释掉了守护进程部分。 @user3121023 确实有效,谢谢! 【参考方案1】:

在第一个调用行上为空,因此分配了一个新缓冲区。之后, line 不为空,因此使用相同的缓冲区。您的数组中充满了指向同一个缓冲区的指针。

【讨论】:

以上是关于使用 C 的 getline() 时的奇怪行为的主要内容,如果未能解决你的问题,请参考以下文章

从 cython c 调用 python 函数时的奇怪行为

尝试使用 tcc 针对 gcc 生成的 .o 文件编译源时的奇怪行为

C++,读取二进制 ifstream 时的奇怪行为

使用 MFMessageComposeViewController 时的奇怪行为

使用 websocket 时的奇怪行为

在模态显示的 UIViewController 中使用 UITableView 时的奇怪行为