更新函数中的字符串数组

Update array of strings in function

我有一个将文件中的行复制到字符串数组中的工作示例。我想移动代码以将行复制到一个函数中,我只需将一个指向字符串数组的指针传递给该函数,行将存储在该数组中,以及一个指向文件的指针。但是,我试图将代码移动到一个函数中并不断出现段错误。我已经尝试使用 GDB 进行调试,问题似乎出在 rows 的内存分配上。但我不知道问题出在哪里。 realloc 似乎工作正常,因为我发现行的大小在第 3 次迭代中增加(使用 malloc_usable_size(*rows)),但随后出现段错误。我正在 Linux.

上使用 gcc -Wall -Wextra -pedantic -std=c99 -g c_programs/read_file_function.c 进行编译

工作示例

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char **argv)
{

  if (argc != 2)
  {
    fprintf(stderr, "Please supply a file path:\n%s <file path>\n", argv[0]);
    return EXIT_FAILURE;
  }
  FILE *fp = fopen(argv[1], "r");
  if (!fp)
  {
    perror("ERROR");
    return EXIT_FAILURE;
  }

  char **rows = (char **)malloc(sizeof(char *));
  char *lineBuf = NULL;
  size_t n = 0;
  size_t nLines = 0;
  ssize_t lineLength = 0;
  size_t i = 0;

  while ((lineLength = getline(&lineBuf, &n, fp)) != -1)
  {
    lineBuf[strcspn(lineBuf, "\n")] = 0;
    lineBuf[strcspn(lineBuf, "\r")] = 0;

    rows[i] = (char *)malloc(lineLength + 1);
    strcpy(rows[i], lineBuf);
    i++;
    nLines = i;
    rows = (char **)realloc(rows, (nLines + 1) * sizeof(char *));
  }

  printf("nLines: %lu\n", nLines);
  printf("row 1: %s\n", rows[0]);
  printf("row 2: %s\n", rows[1]);
  printf("row 2: %s\n", rows[10]);

  return 0;
}

非工作功能版本

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

size_t readFile(FILE **fp, char ***rows)
{
  char *lineBuf = NULL;
  size_t n = 0;
  size_t nLines = 0;
  ssize_t lineLength = 0;
  size_t i = 0;

  while ((lineLength = getline(&lineBuf, &n, *fp)) != -1)
  {
    lineBuf[strcspn(lineBuf, "\n")] = 0;
    lineBuf[strcspn(lineBuf, "\r")] = 0;

    *rows[i] = (char *)malloc(lineLength + 1);
    strcpy(*rows[i], lineBuf);
    i++;
    nLines = i;
    *rows = (char **)realloc(*rows, (nLines + 1) * sizeof(char *));
  }
  return nLines;
}

int main(int argc, char **argv)
{

  if (argc != 2)
  {
    fprintf(stderr, "Please supply a file path:\n%s <file path>\n", argv[0]);
    return EXIT_FAILURE;
  }
  FILE *fp = fopen(argv[1], "r");
  if (!fp)
  {
    perror("ERROR");
    return EXIT_FAILURE;
  }

  char **rows = (char **)malloc(sizeof(char *));
  size_t nLines = readFile(&fp, &rows);

  printf("nLines: %lu", nLines);
  printf("row 1: %s", rows[0]);
  printf("row 2: %s", rows[1]);

  return 0;
}

*rows[i] 正在做 *(rows[i]) - 访问行数组中的第 i 个元素,然后取消引用它。你想做 (*rows)[i] - 取消引用 rows 然后访问第 i 个元素。

我建议:

readFile(..., char ***rows0) {
    char **rows = NULL; // temporary internal variable

    ...
       // use rows normally
       rows = stuff();
    ...
   
    // when finished, assign once
    *rows0 = rows;
    return nLines;
}

但不要成为3-star programmer。充其量,用一个结构,->好用。喜欢:

struct string {
    char *str;
};

struct lines {
    struct string *strs;
    size_t cnt;
};


// @return 0 on success, otherwise error
int readFile(...., struct lines *p) {
    // initialization
    p->cnt = 0;
    p->strs = NULL;

    ...
       void *pnt = realloc(p->strs, (p->cnt + 1) * ....);
       if (!pnt) { /* handle error */ return -1; }
       p->strs = pnt;
       p->strs[p->cnt]->str = malloc(lineLenght + 1);
       if (!p->strs[p->cnt]->str) { /* handle error */ return -2; }
       strcpy(p->strs[p->cnt]->str, lineBuf);
       p->cnt++;
    ...

    return 0; /* success */
}
    

int main(int argc, char **argv) {
   struct lines p = {0};
   if (readFile(..., &p)) {
       /* handle error */
   }
   printf("nLines: %zu\n", p.cnt);

不预分配内存。用NULL初始化内存,调用reallocbefore使用内存。 realloc(NULL 等同于 malloc().

检查分配错误。