c - 使用 C 打印指向字符串的指针数组,省略最后一个字符串

标签 c arrays pointers stdout

我想创建一个指向从 C 文件中读取的字符串的指针数组。但是,当我尝试打印出复制到 stdout 的字符串时,文件的最后一行始终保留出去。 该程序有时还会遇到我无法完全消除的段错误。这种情况大约发生 5 次中的 2 次。

这是我的 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 的调用。

最佳答案

来自 documentation :

If *lineptr is NULL, then getline() will allocate a buffer for storing the line, which should be freed by the user program. (In this case, the value in *n is ignored.)

但在您的情况下,您第一次将未初始化 值传递给getline,因此getline 认为它可以写入该非法值位置,这是未定义的行为(这解释了“5 次中大约有 2 次发生”的事情)

第一个修复应该是初始化:

char *line = NULL;

那么,为什么要创建 line副本,而不释放 line(内存泄漏)不将其重置为 NULL。所以下一次 getline 重用之前的缓冲区,它可能不够长以容纳下一行。

修复只是存储行:

read_lines[i++] = line;

然后设置 line = NULL 以便 getline 为下一行分配适当的长度。并删除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 )

关于c - 使用 C 打印指向字符串的指针数组,省略最后一个字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50864407/

相关文章:

javascript - 如何从 JavaScript 中的数组中删除元素?

c - 使用双指针访问二维数组元素

C - 将数组分配给指针时出现 "incompatible type"警告

C 指针参数不匹配编译警告

将全局数组复制到另一个全局数组

c - C 文件 IO 的奇怪行为

C - 从字节数组的一部分获取字符

无法打印函数返回的字符串

javascript - 为什么 AngularJS 不在它的 isArray 函数中使用 instanceof?

javascript - 如何根据数字范围过滤数组?