在 C 中解析 CSV 值

Parsing CSV Values in C

我正在尝试用 C 编写一个基本的 CSV 解析器,当给定一个 char* 和一个分隔符(例如逗号)时,它会生成一个 char* 的动态数组:

char **filldoc_parse_csv(char *toparse, char sepchar)
{
    char **strings = NULL;

    char *buffer = NULL;

    int j = 0;
    int k = 1;

    for(int i=0; i < strlen(toparse); i++)
    {
        if(toparse[i] != sepchar)
        {
            buffer = realloc(buffer, sizeof(char)*k);
            strcat(buffer, (const char*)toparse[i]);
            k++;
        }
        else
        {
            strings = realloc(strings, sizeof(buffer)+1);

            strings[j] = buffer;

            free(buffer);

            j++;

        }
    }

    return strings;


}

但是,当我按以下方式调用函数时:

char **strings = filldoc_parse_csv("hello,how,are,you", ',');

我遇到了分段错误:

Program received signal SIGSEGV, Segmentation fault.
__strcat_sse2 () at ../sysdeps/x86_64/multiarch/../strcat.S:166
166 ../sysdeps/x86_64/multiarch/../strcat.S: No such file or directory.
(gdb) backtrace
#0  __strcat_sse2 () at ../sysdeps/x86_64/multiarch/../strcat.S:166
#1  0x000000000040072c in filldoc_parse_csv (toparse=0x400824 "hello,how,are,you", sepchar=44 ',') at filldocparse.c:20
#2  0x0000000000400674 in main () at parsetest.c:6

问题的核心是为缓冲区字符串分配足够的 space。如果必须,我会将缓冲区设为静态数组,但是,我想为此目的使用动态内存分配。我怎样才能正确地做到这一点?

您的内存分配有问题。当你这样做时sizeof(buffer) 您将获得 指针 的大小,而不是它指向的内容。这意味着您将在第一个 运行 分配五个字节(在 32 位系统上),下次调用该函数时您将再次 分配五个字节。

还有很多其他的问题,比如你把buffer指针赋值给strings[j]之后就释放了buffer指针。这个问题是赋值只复制指针而不是它指向的东西,所以通过释放 buffer 你也释放了 strings[j].

以上两个问题都会导致您的程序出现undefined behavior,这是导致运行时间崩溃的最常见原因。

您还应避免将 realloc 的结果分配给您尝试重新分配的指针,因为如果 realloc 失败,它将 return NULL 而您松开原始指针导致内存泄漏。

各种问题

  1. strcat(buffer, (const char*)toparse[i]); 尝试将 char 更改为字符串。

  2. strings = realloc(strings, sizeof(buffer)+1); 重新分配相同数量的 space。 sizeof(buffer)是指针buffer的大小,不是它指向的内存大小

  3. 调用函数无法知道 strings 中有多少条目。建议安装一个NULL哨兵。

次要:最好使用 size_t 而不是 int。使用更具描述性的名称。不要重复调用strlen(toparse)。使用 for(int i=0; toparse[i]; i++) 。将 toparse 设为 const char *