小さなCプログラムを書くときにgetline
関数で奇妙な動作が発生しました。ファイルへのファイルへのファイルへ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
の下に、配列から対応する文字列があるはずです。ご覧のように、配列は空の文字列で埋められます。
最初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
1) 'getline'は標準のC関数ではありませんが、POSIX 2)必要のない警告を抑制しないでください。 'return'を追加すると、関数は値を返します! 3) 'char * path_array'は' char'へのポインタであり、配列ではなく 'char'の**配列**を指しています。 4)TL; DRは、[mcve]を提供し、デバッガを使用します。 – Olaf
なぜ 'fork()'ですか? – alk
@それはデーモンになるだろう。デバッグ目的のために私はデーモンの部分をコメントアウトしました。 –