繁体   English   中英

GCC 对于 ARM 报告警告 - 潜在的未初始化变量

[英]GCC for ARM reports warning - potential uninitialized variable

这是生成警告的代码: 'res' may be used uninitialized in this function [-Wmaybe-uninitialized]

lwdtcr_t
lwdtc_cron_parse_multi(lwdtc_cron_ctx_t* cron_ctx, const char** cron_strs, size_t ctx_len, size_t* fail_index) {
    lwdtcr_t res;

    ASSERT_PARAM(cron_ctx != NULL);
    ASSERT_PARAM(cron_strs != NULL);
    ASSERT_PARAM(ctx_len > 0);

    /* Parse all input strings, each to its own cron context structure */
    for (size_t i = 0; i < ctx_len; ++i) {
        if ((res = lwdtc_cron_parse_with_len(&cron_ctx[i], cron_strs[i], strlen(cron_strs[i]))) != lwdtcOK) {
            if (fail_index != NULL) {
                *fail_index = i;
            }
            break;
        }
    }
    return res;
}

断言参数宏定义为

#define ASSERT_PARAM(c)                     if (!(c)) { return lwdtcERRPAR; }
/* Footprint of function being called inside is */
lwdtcr_t
lwdtc_cron_parse_with_len(lwdtc_cron_ctx_t* ctx, const char* cron_str, size_t cron_str_len)

编译器

arm-none-eabi-gcc 10.3.1 20210824 (release)
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

我很难理解为什么会出现此警告? Assert 将在变量为0的情况下启动并立即返回,这意味着for循环将始终执行至少一轮 - 当然如果它到达那一点 - 这意味着res将在 return 语句中初始化。

必须有一个优化技巧 - 但我至少不知道 - 任何线索?

lwdtcr_t是简单的枚举。

如何重现

从这里运行代码: https://godbolt.org/z/9E1xdv4dc

从标志中删除“-Og”神奇地工作而没有任何错误

最小示例

#include <string.h>
#include <time.h>

typedef enum {
    lwdtcOK = 0x00,                             /*!< Everything is OK */
    lwdtcERR,                                   /*!< Generic error */
    lwdtcERRPAR,                                /*!< Invalid parameter passed to a function */
    lwdtcERRTOKEN,                              /*!< Token value is not valid */
} lwdtcr_t;

typedef struct {
    uint32_t flags;                             /*!< List of all sort of flags for internal use */
} lwdtc_cron_ctx_t;

lwdtcr_t    lwdtc_cron_parse_with_len(lwdtc_cron_ctx_t* ctx, const char* cron_str, size_t cron_str_len);

#define ASSERT_PARAM(c)                     if (!(c)) { return lwdtcERRPAR; }

lwdtcr_t
lwdtc_cron_parse_multi(lwdtc_cron_ctx_t* cron_ctx, const char** cron_strs, size_t ctx_len) {
    lwdtcr_t res;

    ASSERT_PARAM(cron_ctx != NULL);
    ASSERT_PARAM(cron_strs != NULL);
    ASSERT_PARAM(ctx_len > 0);

    /* Parse all input strings, each to its own cron context structure */
    for (size_t i = 0; i < ctx_len; ++i) {
        res = lwdtc_cron_parse_with_len(&cron_ctx[i], cron_strs[i], strlen(cron_strs[i]));
    }
    return res;
}

带有标志-Wall -Werror -Wextra -Og

和编译器

arm-none-eabi-gcc 10.3.1 20210824 (release)
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

这是它的基本结构(您可以在发布之前自己完成此简化):

int f (unsigned int len) {
    int res;
    if (len == 0) return 99;
    for (unsigned int i = 0; i < len; ++i)
        res = i;
    return res;
}

这会产生类似的警告。

但是,如果您将res = i替换为res = 99 ,警告就会消失。 所以它看起来像是编译器不是无限聪明的情况。 在这种情况下花太多时间是不值得的; 最简单的修复是用int res = 0;初始化 (附有解释原因的评论)。

它说可以使用未初始化的。 这意味着编译器不确定。 在它说初始化使用的地方给出了不同的警告。

警告的目的是让你再看一遍代码,质疑自己。 如果您已经这样做并且确信编译器在这种情况下是错误的,那么您可以忽略该警告。

如果您不确定,请尝试查看编译器 output 的反汇编列表。

我建议的一件事是,标准库中的宏assert有时会编译为错误检查代码,有时会编译为空,具体取决于编译器设置。 使用 assert 作为宏名称的一部分意味着类似的行为,因此请检查您的构建设置。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM