2016-08-20 2 views
0

小さなCプログラムを書くときにgetline関数で奇妙な動作が発生しました。ファイルへのファイルへのファイルへCのgetline()を使用しているときに奇妙な動作が発生する

  1. リダイレクトstdout
  2. リダイレクトstderr
  3. リダイレクトstdin文字列の配列へのラインによって
  4. 読むstdinライン(char *path_array
  5. :私は何をしたいです
  6. 出力をプリントする

今、私プログラムを実行し、出力は次のようになります。この出力の最後に

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の下に、配列から対応する文字列があるはずです。ご覧のように、配列は空の文字列で埋められます。

最初forのループでは、すべてのアレイ・エントリは現在lineで満たされます:Clionのデバッグモードを使用して

は、私はこれが事実である理由がわかりました。だからではなく、

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 
+0

1) 'getline'は標準のC関数ではありませんが、POSIX 2)必要のない警告を抑制しないでください。 'return'を追加すると、関数は値を返します! 3) 'char * path_array'は' char'へのポインタであり、配列ではなく 'char'の**配列**を指しています。 4)TL; DRは、[mcve]を提供し、デバッガを使用します。 – Olaf

+0

なぜ 'fork()'ですか? – alk

+0

@それはデーモンになるだろう。デバッグ目的のために私はデーモンの部分をコメントアウトしました。 –

答えて

1

はヌルです。その後、lineはnullではないので、同じバッファが使用されます。あなたの配列は同じバッファへのポインタでいっぱいです。

関連する問題