关于潜在未初始化变量的编译器警告

时间:2016-04-20 10:04:31

标签: c gcc error-handling gcc-warning

考虑以下伪代码,它采用典型的错误处理策略和错误代码变量:

Edit1 :当出现uninit var警告时,我添加了另一个用例。不,这个伪代码虽然可编译但实际上并没有触发GCC警告(v4.9.2)但是真正的(更大的)代码在精神上与这个伪代码相同。)

int func1()
{
    int err;
    int a;
    int b;  // *Edit1*

    err = func2( &a ); // init 'a' or fail with 'err'
    if (!err)
    {
        b = 1; // *Edit1*
    }

    if (!err)
    {
        // use variable 'a'
        // here compiler migth produce warning that 'a' might be uninitialized
    }

    if (!err) // *Edit1*
    {
        // use variable 'b'
        // here compiler might produce warning that 'b' might be uninitialized
    }

    return err;
}

GCC会发出一个警告,即变量'a'可能未被初始化。

典型的解决方案是在函数的开头添加(例如)a = 0;。但我正在寻找更通用/优雅的东西。 (编译器无法优化冗余初始化。并非每个变量都有合理的默认值。)

我的问题是:是否有任何编译器功能可能告诉编译器func1()如果未设置a则会初始化err?或者使用错误处理策略实现这一目标的任何其他方法?

P.S。考虑到这种类型的错误处理是如此普遍,我很困惑,我没有找到方法来制作一个没有不必要的任务的无警告代码。

1 个答案:

答案 0 :(得分:-2)

定义之前的所有非静态变量都是未声明的,除非它们已经定义了默认构造函数。大多数基本类型都被认为是原始类型,可以从C继承并遵循C的体系结构 - 在这种情况下,编译器将确定大小,并将在堆栈上分配此大小,仅此而已 - 基础内存是随机的 - 或本身 - 未定义。

如果未定义静态,声明的变量初始化为零 否则。

所有非静态变量都留给内存段中的任何内容,然后声明它 - 这可能会导致未定义的行为,并且在极端情况下 - 信息泄漏。如果使用堆内存 - 它更可取在C语言中调用calloc而不是malloc,在C ++中你真的确保有默认的构造函数,并在调用后进行一些默认操作。

您要完成的是通用编译器功能,其创建用于欺骗未初始化变量的潜在滥用,例如: for (int a; i<0; a++) wchich有潜在危险

请注意,编译器将源文件描述为转换单元 - 它不知道或不关心其他源文件 - 这是链接器作业,用于从已编译的块生成可用的二进制文件。您可以通知您想要的编译器(GNU)或对您正在编写的函数做一些假设,但AFAIK没有适合您的需求link

对所有这些问题都有一个优雅的解决方案,它可以是C ++中的默认构造函数,也可以是C中的基本初始化或calloc归零。

如果它让您烦恼,请将-w添加到gcc / g ++;

我做过的例子:

int err = 0;
int a   = 0;
int b   = 0;

err = func2( &a ); // no warnings
if (!err) b = 1;
if (!err) err = stuff(a);
if (!err) err = stuff(b)

return err;

如果可能的话,还原函数以err作为参数,并生成a作为输出。如果它不可能(lib?)制作包装。如果你对未初始化的参数很好,你应该对calloced参数很好,并且它可以解决你可能遇到的任何问题。这是一种很好的做法,例如,微芯片或Linux内核空间。

somecomplextype * x = (somecomplextype) calloc (1, sizeof(somecomplextype));
if (!x) exit(1);
相关问题