为什么编译器报告 'may be used uninitialised in this function'?
Why compiler report 'may be used uninitialised in this function'?
我正在写一个linux模块,下面是代码fragment.And它
抱怨变量的统一化使用,但我想我已经检查过了
使用前有足够的检查 it.I 认为它可能是相关的
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 日:
我认为根本原因是 long
到 int
的转换。 PTR_ERR()
函数会将指针转换为 long
,但在
上面的代码,test_value_get()
会将 long
转换为 int
,然后 return
到 my_test()
。因为我使用的是 64 位机器,long 可能
被截断到低32位,比如0xfffffffe00000000,
return 值将被削减为 0,然后 if(err)
将不满足,
这导致 test_value
以错误的方式使用。
(虽然 errno 不会大于 4095,但编译器似乎没有意识到它,最接近的溢出值将是 0xfffffffe00000000)
有什么意见吗?
检查下面的执行链
- 在
my_test()
中,test_value_get()
被调用。
test_alloc_value();
失败,if (IS_ERR(p))
为真。
*value = *p;
没有执行。
- 在
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);
}
我正在写一个linux模块,下面是代码fragment.And它 抱怨变量的统一化使用,但我想我已经检查过了 使用前有足够的检查 it.I 认为它可能是相关的 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 日:
我认为根本原因是 long
到 int
的转换。 PTR_ERR()
函数会将指针转换为 long
,但在
上面的代码,test_value_get()
会将 long
转换为 int
,然后 return
到 my_test()
。因为我使用的是 64 位机器,long 可能
被截断到低32位,比如0xfffffffe00000000,
return 值将被削减为 0,然后 if(err)
将不满足,
这导致 test_value
以错误的方式使用。
(虽然 errno 不会大于 4095,但编译器似乎没有意识到它,最接近的溢出值将是 0xfffffffe00000000)
有什么意见吗?
检查下面的执行链
- 在
my_test()
中,test_value_get()
被调用。 test_alloc_value();
失败,if (IS_ERR(p))
为真。*value = *p;
没有执行。- 在
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);
}