原因
在程序中留下难以检测的错误会导致崩溃等不良结果
注意
理想情况下,我们会在编译时或执行时捕捉错误(不包括程序执行逻辑的错误)。
但是,我们不可能在编译器捕捉出所有的错误,通常也无法做到在执行时检出剩下的所有错误
但是,我们还是应该努力按照可检查的原则写代码,就像有充足的资源(分析程序,执行检查,机器资源、时间)那样。
反例
// f是分别编译的,而且有可能是动态加载的。
extern void f(int* p);
void g(int n)
{
// 错误:元素的数量没有传递给 f()
f(new int[n]);
}
在这里,关键信息(元素的数量)已被彻底“模糊”,以至于静态分析可能变得不可行,而动态检查在f()属于ABI的情况下可能非常困难,以至于我们无法“指示”该指针。我们可以将有用的信息嵌入到免费存储中,但这需要对系统甚至对编译器进行全局更改。我们这里的设计使错误检测变得非常困难。
注:ABI(Application Binary Interface)是操作系统为运行在该系统下的应用程序提供的二进制接口。。
反例
我们当然可以把元素的个数和指针一起传递过去:
// separately compiled, possibly dynamically loaded
extern void f2(int* p, int n);
void g2(int n)
{
f2(new int[n], m); // bad: 有可能将错误的元素数量传递给f()
}
相比只是传递一个指针然后通过某种(心照不宣)的转换以获取元素个数的方式,将元素个数作为参数传递会比较好(也更常见)。但是正如代码中显示的,一个简单的打字错误就可能导入严重的错误。函数f2()的两个参数之间的关系可以说约定俗成,但还是没有达到明确的程度。
另外,有一点比较含蓄,就是我们可以推断f2()会释放参数管理的内存(抑或这只是调用者的另一个错误?)
反例
当标准库中的资源管理指针指向一个对象时,如果传递大小信息会导致失败。
// f3s是分别编译的,有可能是动态加载的
// NB:假设调用代码是ABI兼容的,即使用兼容的C++编译器和相同的stdlib实现。
extern void f3(unique_ptr<int[]>, int n);
void g3(int n)
{
f3(make_unique<int[]>(n), m); // 不好: 分别传递所有权和大小
}
译者注:代码前的说明只是make_unique的补充说明,没有看出和本文的主题之间有什么关系。这段代码的问题应该在于同样的大小信息需要两次指定,这同样会带来出错的可能性。
示例
我们需要将指针和元素数量作为一个整体对象进行传递:
extern void f4(vector<int>&); // separately compiled, possibly dynamically loaded
extern void f4(span<int>); // separately compiled, possibly dynamically loaded
// NB:假设调用代码是ABI兼容的(即使用兼容的C++编译器和相同的stdlib实现)。
void g3(int n)
{
vector<int> v(n);
f4(v); // 传递参照,保留所有权
f4(span<int>{v}); // 传递快照,保留所有权
}
这个设计将元素的个数作为对象的一部分,因此不大可能引发错误而且动态(执行时)检查总是可行的,虽然这样做的代价可能十分巨大。
示例
我们如何即传递所有权又传递用于检查的所有信息?
vector<int> f5(int n) // OK: move
{
vector<int> v(n);
// ... initialize v ...
return v;
}
unique_ptr<int[]> f6(int n) // 不好:n 丢失
{
auto p = make_unique<int[]>(n);
// ... initialize *p ...
return p;
}
owner<int*> f7(int n) // 不好:n 丢失,而且有可能会忘记delete
{
owner<int*> p = new int[n];
// ... initialize *p ...
return p;
}
译者注:第一段代码返回一个vector对象,它即包含指针又包含元素个数;第二段代码返回一个unique_ptr,所有权移交没有问题了,但是丢失了元素个数信息;第三段代码不但丢失了元素个数信息,而且没有办法保证内存一定会被删除。非常不幸,第三段代码正是我们日常开发中最常见的代码。
https://blog.csdn.net/sinat_18811413/article/details/108940235
https://blog.csdn.net/craftsman1970/article/details/103262847