c - 如何修复“realloc():无效指针”
问题描述
我正在尝试编写一个将文本文件转换为 CSV 文件的函数。输入文件有 3 行以空格分隔的条目。我必须找到一种将一行读入字符串并将输入文件中的三行转换为 CSV 文件中的三列的方法。
文件如下所示:
Jake Ali Maria
24 23 43
Montreal Johannesburg Sydney
我必须把它变成这样的东西:
Jake, 24, Montreal
...etc
我想我可以创建一个char **line
变量来保存对三个单独char
数组的三个引用,一个用于输入文件的三行中的每一行。即,我的目标是*(line+i)
存储i+1
文件的第 ' 行。
我想避免硬编码char
数组大小,例如
char line1 [999];
fgets(line1, 999, file);
所以我写了一个while循环fgets
,将一行的片段写入一个预定大小的小缓冲区数组,然后根据需要将内存存储为字符串,并strcat
作为指向字符串的指针,其中是第一行,对于第二个等等。realloc
*(line+i)
i
0
1
这是有问题的代码:
#include <stdio.h>
#include<stdlib.h>
#include<string.h>
#define CHUNK 10
char** getLines (const char * filename){
FILE *file = fopen(filename, "rt");
char **lines = (char ** ) calloc(3, sizeof(char*));
char buffer[CHUNK];
for(int i = 0; i < 3; i++){
int lineLength = 0;
int bufferLength = 0;
*(lines+i) = NULL;
do{
fgets(buffer, CHUNK, file);
buffLength = strlen(buffer);
lineLength += buffLength;
*(lines+i) = (char*) realloc(*(lines+i), (lineLength +1)*sizeof(char));
strcat(*(lines+i), buffer);
}while(bufferLength ==CHUNK-1);
}
puts(*(lines+0));
puts(*(lines+1));
puts(*(lines+2));
fclose(file);
}
void load_and_convert(const char* filename){
char ** lines = getLines(filename);
}
int main(){
const char* filename = "demo.txt";
load_and_convert(filename);
}
这仅适用于i=0
. 但是,通过 GDB 进行此操作,我发现我收到了一个realloc(): invalid pointer
错误。缓冲区加载正常,只有当我在 for 循环中调用 'realloc' 时i=1
,当我到达第二行时它才会崩溃。
我设法在一个小示例中存储了我想要的字符串,以尝试查看发生了什么,但输入都在同一行。也许这与fgets
从新行阅读有关?
我真的很感激这方面的帮助,我整天都被困住了。
非常感谢!
***编辑
我尝试按照建议使用calloc
而不是malloc
初始化变量**lines
,但我仍然遇到同样的问题。我已将修改添加到我上传的原始代码中。
***编辑
删除文件并重新编译后,上面的方法现在似乎可以工作了。感谢大家帮助我!
解决方案
您分配line
(这是一个用词不当,因为它不是单行),它是指向三个char*
s 的指针。您永远不会初始化 s 的内容line
(也就是说,您永远不会将这三个char*
s 中的任何一个指向任何地方)。因此,当您这样做时realloc(*(line + i), ...)
,第一个参数是未初始化的垃圾。
要用于realloc
进行初始内存分配,它的第一个参数必须是空指针。line
您应该首先显式初始化to的每个元素NULL
。
此外,*(line+i) = (char *)realloc(*(line+i), ...)
仍然很糟糕,因为如果realloc
分配内存失败,它将返回一个空指针 clobber*(line + i)
并泄漏旧指针。相反,您应该将其拆分为单独的步骤:
char* p = realloc(line[i], ...);
if (p == null) {
// Handle failure somehow.
exit(1);
}
line[i] = p;
还有一些注意事项:
- 在 C 中,您应该避免转换
malloc
/realloc
/的结果calloc
。这不是必需的,因为 C 允许从void*
其他指针类型进行隐式转换,而显式可能会掩盖您不小心省略的错误#include <stdlib.h>
。 sizeof(char)
根据定义,是 1 个字节。- 在分配内存时,养成使用
T* p = malloc(n * sizeof *p);
而不是T* p = malloc(n * sizeof (T));
. 这样,如果类型发生p
了变化,如果您忽略更新malloc
(orrealloc
orcalloc
) 调用,您就不会默默地分配错误的内存量。
推荐阅读
- xpath - 如何在 Excel/Google 表格中抓取网站?
- vba - 如何优化以下 VBA/Excel 代码?
- amazon-web-services - 查询 DynamoDB 时出现空响应
- java - 将字符串转换为int数组后如何正确减去从字符串中取出的2个数字
- php - 我怎样才能在这里避免嵌套循环?使用 php
- angular - 当firebase中的数据发生变化时如何更新快照的本地副本?
- flutter - 如何删除颤振模拟器
- linux - Why Contiguous memory allocation is required in linux?
- r - 将字符 YYYY-MM-00 转换为 R 中的日期 YYYY-MM
- python - LaunchDarkly 带有 celery 的功能标志