【问题标题】:Why compiler report 'may be used uninitialised in this function'?为什么编译器报告“可能在此函数中未初始化”?
【发布时间】:2015-01-29 11:45:18
【问题描述】:

我正在写一个 linux 模块,这里是代码片段。它 抱怨统一使用变量,但我想我已经检查过了 使用前有足够的检查。我认为这可能与 ERR_PTR 和 PTR_ERR 宏,但我不知道为什么。 有人可以帮忙解释一下吗?提前谢谢你。

static inline void * __must_check ERR_PTR(long error)
{
    return (void *) error;
}

static inline long __must_check PTR_ERR(__force const void *ptr)
{
    return (long) ptr;
}

#define MAX_ERRNO       4095
#define IS_ERR_VALUE(x) unlikely((x) >= (unsigned long)-MAX_ERRNO)


static inline bool __must_check IS_ERR(__force const void *ptr)
{
    return IS_ERR_VALUE((unsigned long)ptr);
}

void* test_alloc_value(void)
{
    char* p = kmalloc(100,GFP_KERNEL);
    if(!p)  
            return ERR_PTR(-ENOMEM);
    memset(p,100,0);
    return p;
}

int test_value_get(int *value)
{
    int err = 0;
    char *p;

    p = test_alloc_value();

    if (IS_ERR(p))
            return PTR_ERR(p);

    *value = *p;
    return err;
}

void my_test(void)
{
    int test_value;
    int err = test_value_get(&test_value);
    if(err)
            return err;
    if(test_value) //warnings,see below
            return 0;

}

错误信息是:

warning: ‘test_value’ may be used uninitialized in this function [-Wmaybe-uninitialized]
if(test_value)
   ^

更新:2015 年 1 月 30 日:

我认为根本原因是 longint 的转换。 PTR_ERR() 函数会将指针转换为long,但在 以上代码,test_value_get() 会将long 转换为int,并返回 到my_test()。由于我使用的是64位机器,所以很长可能 被截断到低32位,例如,如果是0xffffffffe00000000, 返回值将被削减为 0,然后if(err) 将不满足, 这导致test_value 以错误的方式使用。 (虽然 errno 不会大于 4095,但编译器似乎没有意识到,最近的溢出值为 0xffffffffe00000000) 有cmets吗?

【问题讨论】:

  • test_value 在哪里声明?
  • int test_value 是全球性的吗?
  • 显然不是您的完整代码,但在test_value_get 中,并非所有可能的路径都会在函数中更改(初始化)test_value(又名value)。
  • 只看到这段代码,可能单元化了!
  • 如果test_value 具有静态存储持续时间,则根据标准将其初始化为零,而且鉴于您发布的代码很少,我看不出它可以是什么,除了吹捧静态存储持续时间. C11 §6.7.9 初始化,p10,“如果它具有算术类型,则将其初始化为(正或无符号)零;”如果不是这样,请发布 MCVE

标签: c initialization compiler-warnings


【解决方案1】:

检查下面的执行链

  1. my_test() 中,test_value_get() 被调用。
  2. test_alloc_value(); 失败,if (IS_ERR(p)) 为 TRUE。
  3. *value = *p; 未执行。
  4. my_test()if(test_value) 展示read-before-write 场景。

这意味着,尽管可能性较小,但仍有一种方法,test_value 可以在未初始化的情况下使用。那么,你的编译器不对吗?

为避免这种情况,在错误情况下 [if (IS_ERR(p)) 为 TRUE。] 同样,将 *value 初始化为某个默认值,例如 0

if (IS_ERR(p))
{
       if (value)                 //NULL pointer safe
            *value = 0;             // set *value in error case also
            return PTR_ERR(p);
}

【讨论】:

  • 如果 IS_ERR(p) 为真,则 OP 代码的修复可能会将 *value 设置为零。
  • @meskobalazs 非常正确,先生。我只是在更新那个。 :-)
  • test_value 不可能未初始化。在您的执行链中,if(err) 必然为真,导致return,因此控制流永远不会到达if(test_value)。唯一的问题是编译器没有意识到这一点。也就是说,警告是误报。
  • @sepp2k 先生,您说的很对,但为了 100% 确定,我们需要查看 PTR_ERR 的定义。没有那个,嗯,从技术上讲,有一种可能性[我希望我应该是错的,虽然]。 :-)
  • 您好,我已经更新了内容,请您帮忙看看,谢谢
猜你喜欢
  • 2012-07-18
  • 1970-01-01
  • 2013-12-29
  • 1970-01-01
  • 2010-12-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多