【问题标题】:C++ Valgrind FIX Conditional jump or move depends on uninitialised value(s)C++ Valgrind FIX 条件跳转或移动取决于未初始化的值
【发布时间】:2020-12-04 20:59:40
【问题描述】:

我像这样使用 valgrind 运行我的程序:

valgrind --leak-check=full ./a.out < in0.txt > out0.txt

并得到以下输出:

==13077== Memcheck, a memory error detector
==13077== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==13077== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==13077== Command: ./a.out
==13077==
==13077== Conditional jump or move depends on uninitialised value(s)
==13077==    at 0x40491F: OnGetMostViewedClasses (in /home/user/a.out)
==13077==    by 0x404498: parser (in /home/user/a.out)
==13077==    by 0x404263: main (in /home/user/a.out)
==13077==
==13077==
==13077== HEAP SUMMARY:
==13077==     in use at exit: 0 bytes in 0 blocks
==13077==   total heap usage: 90 allocs, 90 frees, 6,200 bytes allocated
==13077==
==13077== All heap blocks were freed -- no leaks are possible
==13077==
==13077== For counts of detected and suppressed errors, rerun with: -v
==13077== Use --track-origins=yes to see where uninitialised values come from
==13077== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
-bash-4.2$

虽然它指的是这里使用的StatusType res;

static errorType OnGetMostViewedClasses(void* DS, const char* const command) {
    int numOfClasses;
    int *courses = NULL, *classes = NULL;
    StatusType res;

    ValidateRead(sscanf(command, "%d", &numOfClasses), 1, "%s failed.\n", commandStr[GETMOSTVIEWEDCLASSES_CMD]);
    if (numOfClasses > 0) {
        courses = (int *)malloc(numOfClasses * sizeof(int));
        classes = (int *)malloc(numOfClasses * sizeof(int));
        if (courses == NULL || classes == NULL) {
            res = ALLOCATION_ERROR;
        }
    }

    if (res != ALLOCATION_ERROR) {
        res = GetMostViewedClasses(DS, numOfClasses, courses, classes);
    }

    if (res != SUCCESS) {
        printf("%s: %s\n", commandStr[GETMOSTVIEWEDCLASSES_CMD], ReturnValToStr(res));
        if (courses != NULL) free(courses);
        if (classes != NULL) free(classes);
        return error_free;
    }

    printf("%s: %s\n", commandStr[GETMOSTVIEWEDCLASSES_CMD], ReturnValToStr(res));

    printf("Course\t|\tClass\n");

    for (int i = 0; i < numOfClasses; i++)
    {
        printf("%d\t|\t%d\n", courses[i], classes[i]);
    }

    printf("--End of most viewed classes--\n");

    if (courses != NULL) free(courses);
    if (classes != NULL) free(classes);

    return error_free;
}

并声明如下:

typedef enum {
    SUCCESS = 0,
    FAILURE = -1,
    ALLOCATION_ERROR = -2,
    INVALID_INPUT = -3
} StatusType;

所以我的问题是,我怎样才能解决这个问题更改上面的代码,因为它是给我们的,我的教授告诉我:“你不被允许更改它”和“valgrind 发现的任何错误都会给你一个 0 的标记”?

欢迎任何想法或建议。

请注意:除了这个问题,我有 0 个内存泄漏问题(根据我测试的 32 个输入文件)

【问题讨论】:

  • 你能在启用调试信息的情况下编译这段代码吗(对于 g++,这是 -g 标志),所以 valgrind 可以告诉我们它在抱怨哪一行?这里没有显示任何行号。我们可能还需要查看调用函数(parser)来回答这个问题。即,DS 和 command 是否指向已初始化的内存?
  • "DS 和命令指向初始化内存?"是的,我很确定,我一开始就用 g++ 编译了它(这里发布的那个没有 g++),valgrind 向我展示了以下行“StatusType res;”

标签: c++ enums memory-leaks initialization valgrind


【解决方案1】:

resnumOfClasses 均未初始化。有一些代码路径会导致这些值在 if 语句中使用而没有分配给它们的值。 scanf 可能会失败,使 numOfClasses 未初始化,除非内存分配发生错误,否则 res 不会被赋值。

解决方案是初始化两者:

int numOfClasses = 0;
StatusType res = SUCCESS;

【讨论】:

  • OP 询问如何在不更改代码的情况下解决此问题。
【解决方案2】:

正如@1201ProgramAlarm 指出的那样, res 没有被初始化,并且由于它仅在 numOfClasses 大于零并且其中一个 malloc 调用失败时才被设置,因此您需要以某种方式强制代码进入该代码路径。所以,确保 sscanf 从命令中读取一个值(命令应该是“1”或类似的东西),然后......以某种方式导致 malloc 返回 NULL。这不是微不足道的,但也许您可以在该函数上方的某处添加一条像#define malloc(x) NULL 这样的巧妙行?整个练习看起来很糟糕,TBH。

编辑:或者,通过请求太多内存来使 malloc 失败。如果 numOfClasses 类似于 SIZE_MAX/sizeof(int),则很有可能您将无法分配这么大的两个内存块,并且一个或两个 malloc 调用将返回 NULL。这会设置 res 变量,并且不会有未初始化的读取。愚蠢,愚蠢,愚蠢。

【讨论】:

    【解决方案3】:

    这是标记为 C++,但是带有 typedef enum、void*、malloc、printf 和 scanf 的代码闻起来很 C。这不是学习 C++ 的好方法。

    您没有提供 ValidateRead 的定义。你可能只是能够颠覆预处理器来做你需要的事情,但这会很曲折。

    代码真正应该做的是res = ValidateRead(...,其中 ValidateRead 是一个返回 SUCCESS 或 INVALID_INPUT 的函数。

    【讨论】:

      猜你喜欢
      • 2019-08-14
      • 1970-01-01
      • 1970-01-01
      • 2011-04-18
      • 2016-07-24
      • 2014-11-30
      • 1970-01-01
      • 2017-01-11
      相关资源
      最近更新 更多