我希望创建一个指向从C中的文件读取的字符串的指针数组。但是当我尝试打印出复制到stdout
的字符串时,文件的最后一行总是被省略。
该计划有时也会遇到segmentation fault
我无法完全消除的问题。它发生在大约2次中有5次。
这是我的input.c
代码:
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "input.h"
#define MAXLINES 5000
void writelines(char *arr[], int l);
char *read_lines[MAXLINES];
void get_input(const char *fp) {
FILE *contents;
char *line;
char *temp;
size_t len;
ssize_t read;
int i;
i = 0;
contents = fopen(fp, "r");
if (contents == NULL)
exit(EXIT_FAILURE);
while ((read = getline(&line, &len, contents)) != -1) {
if ((temp = (char *) malloc(strlen(line) + 1)) == NULL) {
printf("Could not allocate required memory.");
exit(EXIT_FAILURE);
}
else {
line[strlen(line) - 1] = '\0';
strcpy(temp, line);
read_lines[i++] = temp;
}
}
fclose(contents);
free(line);
free(temp);
writelines(read_lines, i);
exit(EXIT_SUCCESS);
}
void writelines(char *arr[], int l) {
int i;
for (i = 0; i < l; i++) {
printf("%s\n", arr[i]);
}
}
我的main.c
文件是:
#include <stdio.h>
#include "input.h"
int main(int argc, char *argv[]) {
if (argc == 1)
printf("Please provide a valid source code file.\n");
else
get_input(*(++argv));
return 0;
}
我使用gcc main.c input.c -Wall
进行编译,没有任何警告或错误。
使用gdb
我可以确认该过程正常运行
当遇到分段错误时,后向跟踪会显示对strlen
的调用,显然会失败。
答案 0 :(得分:1)
如果* lineptr为NULL,则getline()将分配用于存储该行的缓冲区,该缓冲区应由用户程序释放。 (在这种情况下,忽略* n中的值。)
但是在您的情况下,您第一次将未初始化的值传递给getline
,因此getline
认为它可以写入该非法位置,这是未定义的行为(这解释了&#34;它发生在5次中的2次&#34;事情)
第一个修复应该是初始化line
:
char *line = NULL;
那么,为什么要创建line
的副本,并且您没有释放line
(内存泄漏)并且您没有重置它到NULL
。所以下次getline
重用前一个缓冲区,这个缓冲区可能不够长,无法容纳下一行。
修复只是存储该行:
read_lines[i++] = line;
然后设置line = NULL
,以便getline
为下一行分配正确的len。并删除malloc
代码,它没用。
固定部分(您不需要在len
上传递指针,它会被忽略):
line = NULL;
while ((read = getline(&line, NULL, contents)) != -1) {
read_lines[i++] = line;
line[strcspn(line, "\n")] = 0; // strip off linefeed if there's one
line = NULL;
}
(换行条改编自Removing trailing newline character from fgets() input)