考虑以下伪代码,它采用典型的错误处理策略和错误代码变量:
( 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。考虑到这种类型的错误处理是如此普遍,我很困惑,我没有找到方法来制作一个没有不必要的任务的无警告代码。
答案 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);