C语言 在调用已知检查参数本身的函数之前检查参数



我想这是代码风格和传统的问题,但问题如下。

假设我们有一个检查参数的函数,例如:

int do_something(int * arr) {
    if (arr == NULL) {
        printf("arr is NULLn");
        return -1;
    }
    ...

现在我们将使用它。问题是:我们应该检查我们将要传递给它的论点吗?因为它无论如何都会检查它。

该示例相当简单,现实生活中的场景可能要困难得多,调用函数会产生更多的参数(和更复杂的检查)和更多的额外开销 - 如果这是某种IPC。

因此,更普遍的问题是:关于这种情况,有哪些共同的准则和做法?

这将基于个人经验和偏见。无论如何,它在这里:

  1. 如果do_something属于库,并且作为可以直接调用的函数向库的用户公开,则最好进行任何和所有必要的检查以确保do_something是健壮的。

  2. 如果它是库中的内部函数,最好还是进行任何和所有必要的检查,以确保do_something是健壮的。我会做而不进行检查的唯一例外是程序/库的性能是否受到检查的不利影响。

  3. 如果它是您自己的应用程序中的函数,则最好进行任何和所有必要的检查,以确保do_something是健壮的。我会做而不进行检查的唯一例外是程序/库的性能是否受到检查的不利影响。

如果函数被记录为检查参数,则调用它而不进行检查。例如,free()被明确记录为接受NULL作为参数,因此编写太常见的参数是没有意义的

if(p != NULL)
  free(p);

它使您的代码混乱而没有任何好处。避免不必要的呼叫的收益通常完全在噪音中被拉出来。

当然,您必须检查函数的返回值。

如果您是函数的实现者,无论是库函数还是本地帮助程序函数,甚至可以在某些编译器上注释函数的特定协定。

例如,如果您的函数不接受 NULL 指针,则可以在函数声明时设置(在 gcc 上)__attribute__((nonnull))

例如,如果您声明:

int do_something(int * arr) __attribute__((nonnull (1)));

你会知道你不能用NULL调用函数(如果编译器知道你这样做,它甚至会发出警告)。但要小心,这个属性可能会让人感到意外。如果您像我一样声明它,并且您仍然会像在示例中那样检查参数,那么您可能会发现优化器从目标代码中完全删除了检查。

相关内容

  • 没有找到相关文章

最新更新