C 库层次结构中的参数检查
在编写函数库时,如果函数参数已经在父函数库中检查过,那么是否应该在子函数库中检查它们,是否存在共识?通过说明,考虑下面的代码片段:C 库层次结构中的参数检查,c,parameters,parent-child,C,Parameters,Parent Child,在编写函数库时,如果函数参数已经在父函数库中检查过,那么是否应该在子函数库中检查它们,是否存在共识?通过说明,考虑下面的代码片段: uint8 er_remove(DE_LIST *deque) { ER_OBJECT *object; uint8 result = ER_BAD_ARGUMENT; if (deque != NULL) { result = de_remove_first(deque, (void **)&object)
uint8 er_remove(DE_LIST *deque)
{
ER_OBJECT *object;
uint8 result = ER_BAD_ARGUMENT;
if (deque != NULL)
{
result = de_remove_first(deque, (void **)&object);
}
return result;
}
假设函数de_remove_first()
也会检查deque
参数是否为NULL,那么在er_remove()中再次检查它是否被认为是一种好形式
从功能角度来看,显然不需要签入er_remove()
。但是,读者可以清楚地看到,deque
参数已被选中,并且它还消除了对签入de_remove_first()
在将来的代码修订中保持不变的依赖
有什么想法吗?不,你没有
er_remove
只是将该参数传递给另一个函数。使用deque
的逻辑完全在de_remove_first
内部实现,在您的情况下,只有您有责任进行检查
如果在de_remove_first
中再次执行此操作,则会使两个函数都绑定到该参数的值。听起来有点过分了。如果将来,de_remove_first
经过优化,可以接受空指针,那么er_remove
会发生什么情况
uint8 er_remove(DE_LIST *deque)
{
ER_OBJECT *object;
uint8 result = ER_BAD_ARGUMENT;
// Will you remember to remove this kind of checks?
if (deque != NULL)
{
// OK, I am now acceptable to a NULL "deque".
result = de_remove_first(deque, (void **)&object);
}
return result;
}
最好的情况是它提醒你这张额外的支票。您可以沿着调用路径找到所有此类检查,并将其删除。最糟糕的是,您忘记了更新它,而在de_remove_first
中接受空参数的代码被绕过,永远不会执行
另一个好处是,调用方不必每次调用er\u remove
或de\u remove\u first
时都检查此参数,从而简化了代码。如果free
是这样设计的呢?想想看
// Check NULL whenever you call free to release a piece of memory
if (ptr != NULL)
{
free(ptr);
}
这取决于库的功能
作为库外部接口的一部分被记录的所有函数-用户调用的函数应该严格地验证它们的参数(或者,至少考虑这样做)。
库内部的函数,即仅由库中的函数调用的函数,不需要对其参数进行额外检查,除非存在只有该函数可以检查的条件。网关(接口)函数应该已经验证了它们的参数,因此内部函数不需要重新验证它们。您仍然可以使用断言检查内部函数,这样,如果函数错误地调用了其中一个内部函数,您就可以在开发过程中发现这一点。但是这些断言永远不应该很少触发。一般来说,需要条件的函数是验证它的地方。请看先决条件、后置条件和不变量。它们不是我以前遇到过的概念-谢谢。这听起来是一种非常明智的方法。非常感谢。