我在C中阅读了以前关于动态数组的问题但是我无法将答案与我的问题联系起来 .
我使用fgets从 stdin
获取命令,删除换行符然后想要在动态分配的字符串数组中存储由空格分隔的每个命令 . 然而,我在分配和重新分配内存的正确方法上遇到了很多麻烦 . 我正在编译 clang
并继续得到分段错误11.然后我使用 -fsanitize=address
并继续获取:
== 2286 ==错误:AddressSanitizer:地址0x60200000eeb8上的堆缓冲区溢出,pc 0x000108fb6f85 bp 0x7fff56c49560 sp 0x7fff56c49558写入大小为8的0x60200000eeb8线程T0
这是我的代码:
// Sets a delimiter to split the input
const char *seperator = " ";
char *token = strtok(line, seperator);
char **cmds = (char **) malloc(sizeof(char) * sizeof(*cmds));
// Adds first token to array of delimited commands
cmds[0] = token;
int count = 1;
while (token != NULL) {
token = strtok(NULL, sep);
if (token != NULL) {
cmds = (char **) realloc(cmds, sizeof(char) * (count + 1));
// Adds next token array of delimited commands
cmds[count] = token;
count++;
}
}
3 回答
你没有分配足够的内存 .
cmds
是一个指针数组,因此每个元素是sizeof(char *)
个字节,而不是sizeof(char)
个字节 .在初始分配上,您需要1
char *
,然后在后续分配中使用count + 1
.此外,don't cast the return value of malloc,因为它可以隐藏其他问题,并且不要忘记检查失败 .
首先,根据定义,
sizeof(char)
始终为1 . 编码不会使您的代码更具可读性 .但是指向
char
的指针需要sizeof(char*)
个字节(取决于机器&ABI,通常为8或4个字节) . 如果使用GCC,我至少建议使用gcc -Wall -Wextra -g
编译代码 .最后,我发现你的代码效率低下 . 你在每个循环中调用
realloc
. 我会维护一个包含分配大小的变量(顺便说一句,总是检查malloc的结果;它可能会失败) .
为了避免
realloc
-ing每次,我会以几何方式增加分配的大小,所以在循环中:或者,不是保留三个变量:
cmds
,count
,allocsize
,您可以使用单个struct
以flexible array member结尾(并保留其分配和使用的大小) .第一个malloc是错的..甚至'll you get when you derefer cmd by *cmd, before it'甚至分配了什么?
它也使用sizeof(char),这是错误的..
正确的方式是......