c - malloc 尝试将输入解析为令牌时出现错误校验和错误
问题描述
我正在尝试创建一个外壳,但我一直遇到错误,
malloc:释放对象的校验和不正确
在我的代码中以及测试时的分段错误中,是否有可能解决此问题?我尝试调试,但在代码中找不到任何异常,有人可以指出我正确的方向吗?
char **getArguments(char line[])
{
/* Pointer to char pointer for storing arguments, initial size is 1 */
char **args = malloc(sizeof(char *));
/* Error handling */
if (args == NULL)
{
fprintf(stderr, "Error: cannot split line.");
exit(EXIT_FAILURE);
}
int count = 0;
/* Try to parse first argument */
char *temp = strtok(line, " \t\n\r\a");
while (temp != NULL)
{
args[count] = temp;
/* Reallocate more space for next argument */
count++;
char **reallocated = realloc(args, count * sizeof(char *));
/* Error handling */
if (reallocated == NULL)
{
fprintf(stderr, "Error: cannot split line.");
exit(EXIT_FAILURE);
}
else
{
args = reallocated;
}
/* Move to next token */
temp = strtok(NULL, " \t\n\r\a");
}
/* NULL terminate the array so that we know where's the end */
args[count] = NULL;
return args;
}
解决方案
初始化count
为 0,然后分配使用args[count]
似乎是问题所在。
该getArguments()
函数最初为参数创建一个单项数组,但随后分配count = 0
- 这应该是1
因为存在第一个元素。
接下来,代码使用全长count
. 显然,在 C 中,数组被索引0
到length-1
,所以my_array[ length ]
永远不正确。
只需初始化count
为 1 并将数组索引固定为 0 偏移即可解决问题。
/* Splits the command into arguments */
char **getArguments(char line[])
{
/* Pointer to char pointer for storing arguments, initial size is 1 */
char **args = malloc(sizeof(char *));
/* Error handling */
if (args == NULL)
{
fprintf(stderr, "Error: cannot split line.");
exit(EXIT_FAILURE);
}
int count = 1; // <-- HERE
/* Try to parse first argument */
char *temp = strtok(line, " \t\n\r\a");
while (temp != NULL)
{
args[count-1] = temp; // <-- HERE
/* Reallocate more space for next argument */
count++;
char **reallocated = realloc(args, count * sizeof(char *));
/* Error handling */
if (reallocated == NULL)
{
fprintf(stderr, "Error: cannot split line.");
exit(EXIT_FAILURE);
}
else
{
args = reallocated;
}
/* Move to next token */
temp = strtok(NULL, " \t\n\r\a");
}
/* NULL terminate the array so that we know where's the end */
args[count-1] = NULL; // <-- HERE
return args;
}
示例输出(通过 Valgrind)
[user@machine]> valgrind ./run_cmds
==8173== Memcheck, a memory error detector
==8173== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==8173== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==8173== Command: ./run_cmds
==8173==
# /bin/echo foo
foo
# /bin/echo 1 2 3 4 5 6 7 8 9 10 11 12 13 14
1 2 3 4 5 6 7 8 9 10 11 12 13 14
# ==8173==
==8173== HEAP SUMMARY:
==8173== in use at exit: 120 bytes in 1 blocks
==8173== total heap usage: 24 allocs, 23 frees, 3,544 bytes allocated
==8173==
==8173== LEAK SUMMARY:
==8173== definitely lost: 0 bytes in 0 blocks
==8173== indirectly lost: 0 bytes in 0 blocks
==8173== possibly lost: 0 bytes in 0 blocks
==8173== still reachable: 120 bytes in 1 blocks
==8173== suppressed: 0 bytes in 0 blocks
==8173== Rerun with --leak-check=full to see details of leaked memory
==8173==
==8173== For lists of detected and suppressed errors, rerun with: -s
==8173== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
也许您的代码被指示realloc()
用作赋值等,但更简单的方法是简单地计算参数的数量,分配args
到正确的大小(完成一次),因此不会循环解析重新分配。
推荐阅读
- javascript - 如何将 JSON 放入 JavaScript 对象数组?
- r - 在 R 中绘制二进制列总和,然后用分类变量的比率覆盖这些列
- python - 问题 ModuleNotFoundError:没有名为“torch._C”的模块
- docker - 在 docker 容器中进行 dotnet 还原期间出现错误
- javascript - “Firefox:当前不支持事件页面”的解决方法。
- excel - Excel VBA 公式名称管理器自动更新源数据
- python - 我们如何用python中的平均值替换数据集中的空单元格
- java - 在 Eclipse 中设置 JavaFX 自包含构建时遇到问题
- amazon-web-services - AWS QuickSight 可以同时使用 Active Directory 和 IAM 登录吗?
- java - 调用 init 方法失败;嵌套异常是 org.hibernate.AnnotationException: No identifier specified for entity