C ++核心准则具有ES.20规则:始终初始化一个object。
避免使用预先设置的错误及其相关的未定义行为。避免理解复杂的初始化问题。简化重构。
但是,此规则无助于发现错误,只会将它们隐藏起来。
假设程序具有执行路径,在该路径中使用未初始化的变量。这是一个错误。除了不确定的行为外,这还意味着出现了问题,程序可能无法满足其产品要求。当将其部署到生产中时,可能会造成金钱损失,甚至更糟。
我们如何筛选错误?我们编写测试。但是测试不能覆盖100%的执行路径,测试也不能覆盖100%的程序输入。不仅如此,即使测试覆盖了错误的执行路径-它仍然可以通过。毕竟,这是未定义的行为,一个未初始化的变量可以具有一个有效值。
但是除了测试外,我们还有一些编译器,它们可以将0xCDCDCDCD写入未初始化的变量。这会稍微提高测试的检测率。
更好的是-有诸如Address Sanitizer之类的工具,它将捕获所有未初始化内存字节的读取。
最后是静态分析器,它可以查看程序并告诉您该执行路径上有一个先读后设置的内容。
因此,我们有许多功能强大的工具,但是如果我们初始化变量清理器,将一无所获。
int bytes_read = 0;
my_read(buffer, &bytes_read); // err_t my_read(buffer_t, int*);
// bytes_read is not changed on read error.
// It's a bug of "my_read", but detection is suppressed by initialization.
buffer.shrink(bytes_read); // Uninitialized bytes_read could be detected here.
// Another bug: use empty buffer after read error.
use(buffer);
还有另一个规则-如果程序执行遇到错误,则程序应尽快死亡。无需保持活动状态,只需崩溃,编写崩溃转储,然后将其交给工程师进行调查即可。
不必要地初始化变量则相反-程序保持活动状态,否则程序将已获得分段错误。
\0
它开头的缓冲区也是错误的。如果有文件证明不予处理,则您的调用代码有问题。如果您bytes_read==0
在调用使用之前修复了调用代码以进行检查,那么您将回到开始的地方:如果不初始化bytes_read
,则代码有错误,如果这样做,则是安全的。(通常,即使发生错误,函数也应填写其参数外:并非如此。通常,输出要么保持不变,要么未定义。)
err_t
返回的my_read()
?如果示例中的任何地方都有错误,就是这样。
bytes_read
且未更改(因此保持为零),为什么这应该是错误?该程序仍然可以以明智的方式继续运行,只要它不会隐式地期望bytes_read!=0
此后。所以很好的消毒剂不要抱怨。另一方面,如果bytes_read
未事先初始化,则程序将无法以合理的方式继续运行,因此未初始化bytes_read
实际上会引入事先未存在的错误。