When should we use asserts in C?

前端 未结 9 1730
孤街浪徒
孤街浪徒 2020-12-02 11:21

I am writing a function in C. As a matter of style, when is it good to use assert compared to returning an error code. Lets say the function is dividing two numbers. Should

相关标签:
9条回答
  • 2020-12-02 11:47

    The conventional wisdom is to use assert() to help debug your code, to warn you when something "impossible", something that must not happen, has happened. This "warning" takes the form of exiting your program.

    I've heard Jim Coplien (general C++ guru and SCRUM trainer) advocate leaving your asserts active in deployed code. (It sounds crazy, I know...) This was specifically for high-reliability server code. The motivation was that it's better to fail, hard, and let another node take over, than to tolerate your server being in an "impossible" state.

    (And of course, track the failures, and analyze them. It means there is a bug or incorrect assumption.)

    0 讨论(0)
  • 2020-12-02 11:49

    This is really a matter of taste. Here is my opinion.

    The main rule of thumb: an assertion failure is always a bug in the program.

    Use an assert to check function parameters if you expect the caller to ensure that the argument is correct and you want to indicate that any other behavior is a bug in the caller. Dividing by zero is, IMO, a very good example.

    Use an error code if you expect the caller not to be able to ensure that the argument is correct before calling. For example, it could be very computationally expensive to check the arguments beforehand.

    Never use an assert to check user input.

    0 讨论(0)
  • 2020-12-02 11:58

    assert aborts the process, but is turned into a no-op when the program is compiled with -DNDEBUG, so it's a rather crude debugging tool and nothing more than that. You should only use assert to check for situations that "can't happen", e.g. that violate the invariants or postconditions of an algorithm, but probably not for input validation (certainly not in libraries). When detecting invalid input from clients, be friendly and return an error code.

    An example use of assert could be: you've implemented an incredibly smart sorting algorithm and you want to check whether it really sorts. Since the sorting function is supposed to "just work" and therefore doesn't return a value, you can't add error returns without changing the API.

    void sort(int *a, size_t n)
    {
        recursive_super_duper_sort(a, 0, n);
        assert(is_sorted(a, n));
    }
    
    static bool is_sorted(int const *a, size_t n)
    {
        for (size_t i=0; i<n-1; i++)
            if (a[i] > a[i+1])
                return false;
    
        return true;
    }
    

    In the long run, you'd really want a proper unit testing framework for this kind of thing instead of assert, but it's useful as a temporary debugging tool.

    0 讨论(0)
  • 2020-12-02 12:01

    Here's a real-world example of an assertion I wrote yesterday.

    I had two parallel arrays -- let's call them a and b -- and I was about to run an index i from 0 up to the size of a, and then do something with a[i] and b[i]. But if there were fewer elements in b than in a, my code would have an array bounds violation on b. But other parts of the code are supposed to keep the sizes of a and b identical. So I put an assertion before the loop, asserting that the sizes of a and b were equal.

    The sizes should be equal -- but if somehow they're not, I want the code to fail on the assertion that tells me why, rather than failing strangely on the Undefined Behavior that would result when I tried to read beyond the end of array b, if it were smaller.

    0 讨论(0)
  • 2020-12-02 12:02

    Since C does not support exceptions you don't have any real option other than to return an error code. A failing C assert() results in abort() being called which bombs the process. That's not really comparable with standard error handling.

    For floating point operations you can use NaN to signal error conditions. For integer operations an error code is simply your only option.

    0 讨论(0)
  • 2020-12-02 12:10

    In general, asserts are for the programmer (i.e. you) to find logic/programming errors before releasing the program to real users. Asserts should not be used for detecting runtime input errors -- use error codes for these.

    0 讨论(0)
提交回复
热议问题