为什么编译器报告'可能在此函数中未初始化'?

时间:2015-01-29 11:45:19

标签: c initialization compiler-warnings

我正在编写一个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)
   ^

更新:01-30-2015:

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

1 个答案:

答案 0 :(得分:4)

检查以下执行链

  1. my_test()中,test_value_get()被调用。
  2. test_alloc_value();失败,if (IS_ERR(p))为真。
  3. *value = *p;未执行。
  4. 位于my_test()if(test_value)展示了read-before-write广告。
  5. 这意味着,尽管可能性较小,但仍有一种方法, 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);
    }