如果我不进行memset,则通过堆分配创建未初始化的值

时间:2016-05-06 14:33:01

标签: c malloc valgrind memset

我感兴趣的是这个。

char *assign_value = (char*)malloc(10 * sizeof(char));
if(strlen(assign_value) == 0) {
    strcpy(assign_value, "A");
} else {
    strcat(assign_value, "A");
}

基本上在上面的示例中,我将得到未初始化值由堆分配创建的错误。但是如果我做了以下事情并在malloc()和if语句之间插入memset()我将看不到同样的错误。我想听一些消息,这是正确的方法,如果不是,那么做什么是正确的?

char *assign_value = (char*)malloc(10 * sizeof(char));
memset(assign_value, 0, sizeof(assign_value));
if(strlen(assign_value) == 0) {
    strcpy(assign_value, "A");
} else {
    strcat(assign_value, "A");
}

谢谢!

3 个答案:

答案 0 :(得分:2)

问题来自于strlen(assign_value)未{初始化assign_value时调用malloc(10)

以下是修复问题的三种方法:

  • 您可以使用memset(assign_value, 0, 10);手动设置数组的所有字节。请注意,您的调用不正确,因为sizeof(assign_value)评估为指针的大小,而不是数组的大小。

  • 您可以使用calloc(10, sizeof(char))分配数组。 calloc返回初始化为所有位零的内存块的地址,这与调用memset具有相同的效果,但可能更有效。

  • 您可以将初始字节设置为'\0',使数组为空字符串,适用于strcpystrcat

如果在使用前未能初始化任何或所有已分配的数据,则使用calloc()代替malloc()是避免不可预测行为的好习惯。

请注意,您的代码可以从根本上简化:如果目标字符串确实为空,则调用strcat() 等同于strcpy()。你可以写:

char *assign_value = calloc(10, sizeof(char));
...
strcat(assign_value, "A");

此外,您应该通过检查已经存储在缓冲区中的字符串的长度来验证strcat()不会导致缓冲区溢出:

char *assign_value = calloc(10, sizeof(char));
...
if (strlen(assign_value) < 10 - 1) {
    strcat(assign_value, "A");
} else {
    // handle the error: not enough space in assign_value
}

答案 1 :(得分:1)

是的,你从malloc回来的记忆是未初始化的。通常,它将包含不可预测的随机值。偶然的随机值可能为0 - 但你根本不能指望它。

所以,是的,如果您在意,您必须始终初始化从malloc返回的内存。一种方法是调用memset - 尽管你发布的例子很不寻常。如果你想将你刚回来的所有内存归零,那么通常的呼叫就是

memset(assign_value, 0, 10);

(而不是malloc,您也可以使用callocmalloccalloc之间的差异是calloc自动初始化新分配记忆全部为0。)

如果您使用assign_value作为字符串,并且希望将其作为空字符串开始,则不必将其全部清零。仅将空字符放在第一个位置就足够了:

*assign_value = '\0';

完成上述任何操作后,assign_value将保留一个空字符串,长度为0.因此,您的测试if(strlen(assign_value) == 0)将始终成功,并且在以后的代码中,您将始终结束致电strcpy,而不是strcat

最后,作为侧点,在调用sizeof(char)时,您不必乘以malloc或投射结果。所以你可以使用更简单的方法:

char *assign_value = malloc(10);

(您不必乘以sizeof(char),因为根据定义,sizeof(char)始终是1.您不必在C中显式地转换malloc的结果,如果你这样做,它可以隐藏错误。)

答案 2 :(得分:0)

malloc()分配内存但不初始化它。无论分配到的内存位置是什么,都是你得到的 因此,在使用malloc时,最好创建并初始化缓冲区:

char *assign_value;
assign_value = malloc(10 * sizeof(char));
memset(assign_value, 0, 10);
另一方面,

calloc()分配内存并初始化分配给0的所有位置:

char *assign_value = calloc (10,1);//note sizeof(char) is always 1

如需更多阅读,请参阅 comparing malloc() and calloc()

请注意,没有必要像在C ++中那样在C中转换[m] [c] alloc的输出。