C 条件移动基于未初始化的值,未初始化的值是通过堆分配创建的

C 条件移动基于未初始化的值,未初始化的值是通过堆分配创建的,c,malloc,valgrind,C,Malloc,Valgrind,嗨,我从valgrind得到以下错误 条件移动基于未初始化的值,通过堆分配创建未初始化的值 编译器没有抱怨 我在stackoverflow上查看了大多数类似的错误,但我似乎无法指出我的错误 #include <stdio.h> #include <stdlib.h> #include <ctype.h> #include <string.h> int main(void) {

嗨,我从valgrind得到以下错误

条件移动基于未初始化的值,通过堆分配创建未初始化的值

编译器没有抱怨

我在stackoverflow上查看了大多数类似的错误,但我似乎无法指出我的错误

    #include <stdio.h>
    #include <stdlib.h>
    #include <ctype.h>
    #include <string.h>

    int
    main(void)
     {

      char *string1 = malloc(45);
      char string2[25] = "HELLO WORLD";
      strcpy(string1,string2);
      printf("String one is %s\n",string1);

      char string3[25];
      for (int i = 0; i < 25; i++)
       {
        string3[i] = tolower(string1[i]);

       }
      printf("The output is %s\n",string3);
      free(string1);
      return 0;

    }
#包括
#包括
#包括
#包括
int
主(空)
{
char*string1=malloc(45);
char string2[25]=“你好,世界”;
strcpy(string1、string2);
printf(“字符串一是%s\n”,string1);
字符串3[25];
对于(int i=0;i<25;i++)
{
string3[i]=tolower(string1[i]);
}
printf(“输出为%s\n”,string3);
自由(1);
返回0;
}

您正在沿
string1
从0循环到24,该字符串仅被初始化
strlen(“HELLO WORLD”)+1
字节。索引从12到24的字节尚未初始化,您不应该尝试读取它们。您应该使用
calloc()
分配
string1
或使用
memset()
初始化它,如下所示:

char *string1 = calloc(1, 45);


或者您可以使用上述方法将
string3
初始化为零,然后只复制
strlen(string1)
字节。

您将沿着
string1
从0循环到24,该字符串仅被初始化
strlen(“HELLO WORLD”)+1
字节。索引从12到24的字节尚未初始化,您不应该尝试读取它们。您应该使用
calloc()
分配
string1
或使用
memset()
初始化它,如下所示:

char *string1 = calloc(1, 45);


或者您可以使用上述方法将
string3
初始化为零,然后只复制
strlen(string1)
字节。

您的
tolower
调用访问
string1
指向的内存的前25个字节,但只有该内存的前12个字节处于有效状态(感谢
strcpy

您可以使用
calloc
而不是
malloc
以确定性状态分配内存。或者,只复制所需的字节数:

{
    const unsigned int M = max(24, strlen(string1));
    for (unsigned int i = 0; i != M; ++i)
        string3[i] = tolower(string1[i]);
    string3[M] = 0;
}

您的
tolower
调用访问由
string1
指向的内存的前25个字节,但只有该内存的前12个字节处于有效状态(多亏了
strcpy

您可以使用
calloc
而不是
malloc
以确定性状态分配内存。或者,只复制所需的字节数:

{
    const unsigned int M = max(24, strlen(string1));
    for (unsigned int i = 0; i != M; ++i)
        string3[i] = tolower(string1[i]);
    string3[M] = 0;
}

还有更多的行信息吗?您可以尝试使用
--track origins=yes
运行它吗?这可能会帮助您找出问题所在,尽管在本例中您只进行了一次堆分配,因此它可能是
string1
@DanFego,是的,我使用--track origins=yes运行它。如果没有track命令,它将显示基于条件的跳转在未初始化的值上。是否有更多的行信息?是否可以尝试使用
--track origins=yes
?这可能有助于确定问题,尽管在本例中,您只进行了一次堆分配,因此它可能是
string1
@DanFego,是的,我正在使用--track origins=yes运行它。如果没有track命令,它将停止运行ws-conditional jump基于未初始化的值。是的,删除tolower()会使其消失。但是有没有其他方法,不删除它?谢谢,我会尝试一下。@kevin:您可能应该使循环只上升到
max(24,strlen(string1))
,然后别忘了将最后一个设置为零。我添加了代码。@凯文:作为说明,我可能更喜欢受限循环而不是
calloc
,因为你想要的是转换字符串,而不是填充25个字节的内存。没有理由强迫你进行无意义的内存初始化使用,限制循环更“慎重”。我也这么认为。但是如果在节省空间和快速运行时间之间做出选择,你会选择哪一个?请注意,这个逻辑是另一个程序的一部分(实现快速拼写检查)。我从valgrind中分离出这段代码来查找错误。是的,删除tolower()让它消失。但是有没有别的办法,不移除它?谢谢,我会试试。@kevin:你应该让循环只上升到
max(24,strlen(string1))
,然后别忘了将最后一个设置为零。我添加了代码。@凯文:作为说明,我可能更喜欢受限循环而不是
calloc
,因为你想要的是转换字符串,而不是填充25个字节的内存。没有理由强迫你进行无意义的内存初始化使用,限制循环更为“慎重”。我也这么认为。但如果在节省空间和快速运行时间之间做出选择,您会选择哪一个?请注意,此逻辑是另一个程序的一部分(用于实现快速拼写检查)。我隔离了这段代码以从valgrind中查找错误。谢谢,我将尝试使用calloc和memset。@kevin,为了清楚起见,您可能只想执行
calloc()
版本。我刚刚在
malloc()
/
memset()
位中留下来显示您试图通过初始化完成的任务。。)谢谢,我将尝试使用calloc和memset。@凯文,为了清楚起见,您可能只想使用
calloc()
版本。我刚刚离开了
malloc()
/
memset()
位,以显示您试图通过初始化实现的功能