如果我不做 memset,未初始化的值是由堆分配创建的

Uninitialized value was create by a heap allocation if i don't do 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");
}

谢谢!

是的,您从 malloc 取回的内存未初始化。通常,它将包含不可预测的随机值。碰巧随机值 可能 为 0 -- 但您根本不能指望这一点。

所以,是的,如果您关心的话,您必须始终初始化从 malloc 取回的内存。一种方法是调用 memset——尽管您发布的示例很不寻常。如果你想将刚刚取回的所有内存归零,通常的调用是

memset(assign_value, 0, 10);

(除了malloc,你也可以使用callocmalloccalloc的区别在于calloc会自动初始化新的- 分配内存给所有 0.)

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

*assign_value = '[=11=]';

一旦你做了任何这些事情,assign_value 将保存一个空字符串,长度为 0。所以你的测试 if(strlen(assign_value) == 0) 总是会成功,并且在你以后的代码中你会总是以 strcpy 结束,从不 strcat.

最后,作为补充,您不必乘以 sizeof(char),也不必在调用 malloc 时转换结果。所以你可以使用更简单的:

char *assign_value = malloc(10);

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

问题出在 assign_value 未初始化时调用 strlen(assign_value),由 malloc(10) 返回。

以下是解决问题的三种方法:

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

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

  • 您可以将初始字节设置为 '[=20=]' 以使数组成为空字符串,同时适用于 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
}

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 的输出。