我正在开发一个功能,使用stdin
从char*
读取整个行到getchar()
,它主要起作用,但当我输入更长的字符串时,我得到< / p>
realloc():下一个大小无效:0x00000000007ca010
这是功能:
char *readCMDLine() {
char *cmdline = malloc(sizeof(char));
int counter = 0;
char c;
while (c != 10) {
c = getchar();
cmdline = realloc(cmdline, sizeof(cmdline) + sizeof(char));
cmdline[counter] = c;
counter++;
}
return cmdline;
}
有没有办法解决这个问题,以便我可以用它读取更大的行?
答案 0 :(得分:4)
使用sizeof(cmdline)
并没有达到预期效果。当与指针一起使用时,它将返回指针的大小,而不是分配的内存。这对于在编译时定义的数组是不同的。
您可以使用counter
变量来跟踪已分配的字节数。
也是一种风格的东西:sizeof(char)
总是1,所以没必要。
在每个角色之后重新分配是不符合要求的。最好分配一个体积适中的缓冲区,当它完全分配一个更大的缓冲区时。
答案 1 :(得分:3)
这里的问题是,
sizeof(cmdline)
不像你想象的那样工作。您无法使用指针上的sizeof
来获取已分配内存的大小。你必须自己跟踪大小。
现在,要在错误上添加一点,
realloc():下一个大小无效:0x00000000007ca010
基本上会发生什么,
cmdline = realloc(cmdline, sizeof(cmdline) + sizeof(char));
实际上并没有按照您的想法调整分配的内存。因此,当counter
值足够大以指向cmdline[counter]
的情况下的超出内存时,您基本上会调用undefined behavior。因此,由于UB(以及随后的内存损坏),realloc()
会发出错误并引发分段错误作为副作用。
另外,要添加
第1点:
pointer = realloc(pointer....)
是一种非常糟糕的语法。如果realloc()
失败,你最终也会失去实际的内存,因为它会被NULL取代。
第2点:
getchar()
返回int
,所有返回值可能不适合char
(例如EOF
)。将c
的类型更改为int
。
第3点:
您可能希望在返回字符串之前将其终止,以使其可用于字符串操作函数,并且适用于%s
中的printf()
。
第4点:
在使用返回的指针之前,您应该检查malloc()
和realloc()
是否成功。
答案 2 :(得分:3)
您的代码存在多个问题:
while (c != 10)
,但第一次未初始化c
,并且您不允许该文件在下一个'\n'
之前结束。您还假设ASCII,某些系统仍然使用EBCDIC,其中'\n'
不是10
。sizeof(cmdline)
代替counter
重新分配。 sizeof(cmdline)
是指针的大小,而不是当前分配的数组大小。getchar()
存储到char
变量中,EOF
不是可以适合的值,128
和UCHAR_MAX
之间的值也可能char
{1}}已在您的平台上签名。请使用int
。malloc
没有realloc
初始化已分配的内存。malloc
或realloc
失败。NULL
,否则无法从空行序列中判断文件结尾。以下是更正后的版本:
#include <stdlib.h>
char *readCMDLine(void) {
char *cmdline = malloc(1);
size_t counter = 0, size = 1;
int c;
if (cmdline == NULL)
return NULL;
while ((c = getchar()) != EOF && c != '\n') {
char *p = realloc(cmdline, counter + 2);
if (p == NULL) {
free(cmdline);
return NULL;
}
cmdline = p;
cmdline[counter++] = c;
}
cmdline[counter] = '\0';
if (c == EOF && counter == 0) {
free(cmdline);
cmdline = NULL;
}
return cmdline;
}
这是一个优化版本,可以更少地调用realloc:
#include <stdlib.h>
#define ALLOCATE_INCREMENT 100
char *readCMDLine(void) {
char *p, *cmdline = NULL;
size_t counter = 0, size = 0;
int c;
while ((c = getchar()) != EOF && c != '\n') {
if (counter > size - 2) {
p = realloc(cmdline, size += ALLOCATE_INCREMENT);
if (p == NULL) {
free(cmdline);
return NULL;
}
cmdline = p;
}
cmdline[counter++] = c;
}
if (counter == 0) {
if (c == EOF || (cmdline = malloc(1)) == NULL)
return NULL;
} else {
p = realloc(cmdline, counter + 1);
if (p != NULL)
cmdline = p;
}
cmdline[counter] = '\0';
return cmdline;
}
答案 3 :(得分:2)
结合所有建议:
#define BYTES_TO_ADD 80 /* a rather arbitrary number */
char * readCMDLine ( void ) {
char * cmdline = NULL;
size_t cmdSize = 0;
size_t cmdLen = 0;
int c;
while ((c = getchar()) != EOF) {
if (cmdLen == cmdSize) {
char * tmp = realloc(cmdline, (cmdSize += BYTES_TO_ADD));
if (tmp == NULL) { free(cmdline); return NULL; }
cmdline = tmp;
}
cmdline[cmdLen++] = (c == '\n') ? '\0' : c;
if (c == '\n') return cmdline;
}
return NULL; /* no newline */
}