我正在编写一个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:
我认为根本原因是long
到int
转换。 PTR_ERR()
函数会将指针转换为long
,但在
在上面的代码中,test_value_get()
会将long
转换为int
,然后将其返回
到my_test()
。因为我使用的是64位机器,所以很长时间
例如,如果它是0xfffffffe00000000,则被切断为低32位,
返回值将被剪切为0,然后if(err)
将不满足,
这导致test_value
以错误的方式使用。
(虽然errno不会大于4095,编译器似乎没有意识到它,最近的溢出值将是0xfffffffe00000000)
有什么意见吗?
答案 0 :(得分:4)
检查以下执行链
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);
}