簡體   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