我在下面的代码中收到了一个单一化的警告,我很难理解为什么。 我看不到未经初始化使用的代码路径。任何人都可以帮忙吗? 另外,我可以使用一些adivce,如果我的gotos使用不好或者有更干净的方法这样做。
In function ‘handle_comp_enc’:
fs/compress.c:101:8: warning: ‘write_cdata’ may be used uninitialized in this function [-Wmaybe-uninitialized]
kfree(write_cdata);
代码:
#define ENC (1UL << 1)
#define ZIP (1UL << 2)
#define ENC_ZIP_ENABLED(cmp_enc_flags) ((cmp_enc_flags) & (ENC | ZIP)) == (ENC | ZIP)
int handle_comp_enc(unsigned long comp_enc_flags, unsigned char *read_data,
size_t read_len, unsigned char *write_data, size_t *write_len2) {
unsigned char *write_cdata, *rd_enc_data;
size_t write_clen, enc_src_len;
int err;
if (ENC_ZIP_ENABLED(comp_enc_flags)){
write_cdata = kmalloc(get_compress_fsize(PAGE_SIZE), GFP_KERNEL);
if (!write_cdata) {
err = -ENOMEM;
goto zip_only;
}
}
else if(!(comp_enc_flags & ENC))
write_cdata = write_data;
else{
rd_enc_data = read_data;
enc_src_len = read_len;
goto enc_only;
}
err = do_compress(read_data, read_len, write_cdata, &write_clen);
if (err < 0) {
goto out_enc_zip;
}
if (!(comp_enc_flags & ENC)) {
*write_len2 = write_clen;
goto zip_only;
}
rd_enc_data = write_cdata;
enc_src_len = write_clen;
enc_only:
err = do_skcipher_encrypt(rd_enc_data, enc_src_len, write_data, write_len2);
if (err < 0) {
}
out_enc_zip:
if (ENC_ZIP_ENABLED(comp_enc_flags))
kfree(write_cdata);
zip_only:
return err;
}
答案 0 :(得分:3)
编译器最好发出警告,因为消息说&#34;也许&#34;,编译器不知道标签{ENC_ZIP_ENABLED(comp_enc_flags)
将是假的out_enc_zip
1}}。您的代码未使用未初始化的值。
那就是说,我强烈不同意你的goto
用例,你的代码是不可读的,我花了很多时间来了解代码的去向。
您的代码可能会被简化很多,我不确定此代码是否与我所说的代码难以阅读的行为相同:
#define ENC (1UL << 1)
#define ZIP (1UL << 2)
int handle_comp_enc(unsigned long comp_enc_flags, unsigned char *read_data,
size_t read_len, unsigned char *write_data, size_t *write_len2) {
if ((comp_enc_flags & (ENC | ZIP)) == (ENC | ZIP)) {
unsigned char *tmp = kmalloc(get_compress_fsize(PAGE_SIZE), GFP_KERNEL);
if (!tmp) {
return -ENOMEM;
}
size_t size;
int err = do_compress(read_data, read_len, tmp, &size);
if (!(err < 0)) {
err = do_skcipher_encrypt(tmp, size, write_data, write_len2);
}
kfree(tmp);
return err;
}
else if (!(comp_enc_flags & ENC)) {
return do_compress(read_data, read_len, write_data, write_len2);
}
else {
return do_skcipher_encrypt(read_data, read_len, write_data, write_len2);
}
}
答案 1 :(得分:1)
是的,这看起来像是误报。在if-else if-else中,您只在if
和else if
语句中初始化变量。显然你得到的工具与goto或其他一些混淆。
但这并不重要,因为问题的根源是功能设计。您没有默认初始化变量,并且您在内存分配和实际算法之间存在紧密耦合。在这里使用goto是可以的,但它会稍微降低可读性。
我会将它拆分为两个函数,将内存处理和错误处理留给外部函数。这段伪代码的某些内容会更具可读性:
int wrapper_function ( ... )
{
unsigned char *write_cdata = NULL;
int err = initialize_me_to_something.
if(ENC_ZIP_ENABLED(comp_enc_flags))
{
write_cdata = kmalloc (...
if(write_cdata == NULL)
{
return -ENOMEM;
}
}
else
{
if(!(comp_enc_flags & ENC)
{
write_cdata = write_data;
...
}
else
{ // some special case
err = do_skcipher_encrypt(...
return err;
}
}
err = do_the_actual_job(write_cdata, otherparameters);
if (err < 0)
{
cleanup();
}
return err;
}
goto
不一定是邪恶的,但也不是多个返回语句。他们对所提供的或多或少理性的论点都不满意。但是,多个return语句往往比“on error goto”模式提高了可读性。最重要的是,他们倾向于自然地提供更好的程序设计,具有多个小功能而不是单个大功能。
作为副作用,您可以省去一些额外的分支指令,这可能会略微提升性能。