【问题标题】:C - Conditional jump or move depends on uninitialised value(s)C - 条件跳转或移动取决于未初始化的值
【发布时间】:2013-11-20 14:23:39
【问题描述】:

当我尝试运行我的程序时,我从 Valgrind 收到此错误:

==23152== Conditional jump or move depends on uninitialised value(s)
==23152==    at 0x4C2D8D0: strcmp (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==23152==    by 0x40096C: str_lower_cmp (functions.c:41)
==23152==    by 0x400BB8: list_sort (list_sort.c:34)
==23152==    by 0x400CC7: get_wdir_content (working_dir.c:27)
==23152==    by 0x400C27: main (main.c:18)
==23152==  Uninitialised value was created by a heap allocation
==23152==    at 0x4C2C27B: malloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==23152==    by 0x400D4C: xmalloc (xfunctions.c:35)
==23152==    by 0x400886: lower_string (functions.c:20)
==23152==    by 0x400945: str_lower_cmp (functions.c:39)
==23152==    by 0x400BB8: list_sort (list_sort.c:34)
==23152==    by 0x400CC7: get_wdir_content (working_dir.c:27)
==23152==    by 0x400C27: main (main.c:18)
==23152== 
==23152== Conditional jump or move depends on uninitialised value(s)
==23152==    at 0x400BBB: list_sort (list_sort.c:34)
==23152==    by 0x400CC7: get_wdir_content (working_dir.c:27)
==23152==    by 0x400C27: main (main.c:18)
==23152==  Uninitialised value was created by a heap allocation
==23152==    at 0x4C2C27B: malloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==23152==    by 0x400D4C: xmalloc (xfunctions.c:35)
==23152==    by 0x400886: lower_string (functions.c:20)
==23152==    by 0x400945: str_lower_cmp (functions.c:39)
==23152==    by 0x400BB8: list_sort (list_sort.c:34)
==23152==    by 0x400CC7: get_wdir_content (working_dir.c:27)
==23152==    by 0x400C27: main (main.c:18)
==23152==

虽然我不能说哪里出了问题,但我猜它来自 list_sort.c :

t_llist  *list_sort(t_llist *list)
{
    struct s_node *tmp;

    tmp = list->head;
    while (tmp != NULL)
    {
        if (tmp->next != NULL)
        {
            if (!tmp->name || !tmp->next->name)
                printf("Reached.\n");
            if (str_lower_cmp(tmp->name, tmp->next->name) > 0)
            {
                data_swap(tmp, tmp->next);
                tmp = list->head;
            }
            else
                tmp = tmp->next;
        }
        else
            return (list);
    }
    return (list);
}

这是否意味着在某些时候,tmp->name 或 tmp->next->name 值未初始化?

编辑(functions.c 代码)

    char            *lower_string(char *s)
{
  char          *res;
  int           i;

  i = 0;
  res = xmalloc(sizeof(*res) * strlen(s) + 1);
  while (s[i])
    {
      if (s[i] >= 'A' && s[i] <= 'Z')
        res[i] = s[i] + 32;
      else
        res[i] = s[i];
      i++;
    }
  s[i] = '\0';
  return (res);
}

int             str_lower_cmp(char *s1, char *s2)
{
  char          *tmp1;
  char          *tmp2;
  int           res;

  tmp1 = lower_string(s1);
  tmp2 = lower_string(s2);
  res = strcmp(tmp1, tmp2);
  free(tmp1);
  free(tmp2);
  return (res);
}

【问题讨论】:

  • 嗯,如果在使用前检查列表指针会怎样?
  • 对不起,哪个指针? t_llist *list ?
  • 由于报告在strcmp 中,您可以推断您正在为节点分配内存,这是使用 valgrind 调试分配器进行模式填充,然后检查所述指针值模式由他们调试 strcmp。换句话说,是的,您可能会通过值或从未正确填充和终止它指向的实际数据来发送不确定的name 参数。如果不知道您实际上是如何构建您的列表,就不可能说出您是如何犯这个错误的。
  • 是的,它甚至会告诉你你在哪里 malloc'ed 字符串但没有填写:lower_string functions.c:20
  • @DaanTimmer 老实说,最好不要这样做根本,考虑到它甚至不需要。

标签: c linked-list valgrind


【解决方案1】:

最初valgrind 告诉您,您正在运行strcmp,其内存地址由malloc 分配,来自函数lower_string,但没有分配初始值。

这意味着未定义的行为,这意味着根据您的代码,可能非常危险,因为可能会导致意外结果。

我建议在lower_string 中使用calloc

编辑:您将 s[i] 设置为 0 而不是 res[i](您分配并返回的指针)。另一方面,我建议使用calloc 并检查res!=NULL

【讨论】:

  • @WhozCraig 我同意。更新了回复;)。但是,为了澄清,我的意思是,对于strcmp,它很可能会立即返回,您将进入else 块(我假设有一个if/else 检查strcmp 响应)
  • 我在我的 xmalloc 函数中调用 malloc,在那里我检查它的返回。
  • @Kernael 然后,只需调用calloc 而不是malloc,您将所有分配的内存初始化为0
  • @Kernael 这对修复您的警告消息有用吗?
【解决方案2】:

你的错误在这里lower_string 你没有终止你正在分配的字符串:

char *lower_string(char *s)
{
    char *res;
    int i;

    i = 0;
    res = xmalloc(sizeof(*res) * strlen(s) + 1);
    while (s[i])
    {
        if (s[i] >= 'A' && s[i] <= 'Z')
            res[i] = s[i] + 32;
        else
            res[i] = s[i];
        i++;
    }
    s[i] = '\0'; // THIS IS WRONG
    return (res);
}

标记的行应该是这样的:

    res[i] = '\0'; // THIS IS RIGHT

请注意,如果您正确地将输入字符串作为const 参数传递,这将被捕获:

char *lower_string(const char *s) // MAKE PARAM CONST

这样做会导致编译失败,因为您的s[i] = '\0' 赋值违反了 const 条件。一般规则,除非您需要修改作为按地址参数传递的内容,否则将其设为const

【讨论】:

  • 谢谢,最后真是个愚蠢的错误。也谢谢你的提示,我会用的。
  • @Kernael 如果您认为那是“愚蠢的”,您将最不高兴知道您可以实现 str_lower_cmp 而根本没有动态分配,从而使问题一开始就不是问题.考虑一下。
【解决方案3】:

当传递给 lower_string 的 "char *s" 是一个空字符串时,您的程序也会崩溃。像 jcm 所说的那样调用 calloc 将有助于解决这个问题

【讨论】:

    猜你喜欢
    • 2019-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-18
    • 2011-08-18
    相关资源
    最近更新 更多