在 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
而您松开原始指针导致内存泄漏。
各种问题
strcat(buffer, (const char*)toparse[i]);
尝试将 char
更改为字符串。
strings = realloc(strings, sizeof(buffer)+1);
重新分配相同数量的 space。 sizeof(buffer)
是指针buffer
的大小,不是它指向的内存大小
调用函数无法知道 strings
中有多少条目。建议安装一个NULL
哨兵。
次要:最好使用 size_t
而不是 int
。使用更具描述性的名称。不要重复调用strlen(toparse)
。使用 for(int i=0; toparse[i]; i++)
。将 toparse
设为 const char *
我正在尝试用 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
而您松开原始指针导致内存泄漏。
各种问题
strcat(buffer, (const char*)toparse[i]);
尝试将char
更改为字符串。strings = realloc(strings, sizeof(buffer)+1);
重新分配相同数量的 space。sizeof(buffer)
是指针buffer
的大小,不是它指向的内存大小调用函数无法知道
strings
中有多少条目。建议安装一个NULL
哨兵。
次要:最好使用 size_t
而不是 int
。使用更具描述性的名称。不要重复调用strlen(toparse)
。使用 for(int i=0; toparse[i]; i++)
。将 toparse
设为 const char *