简体   繁体   中英

Apart from -Wall and -Wextra what other tools are available to spot as many errors or warnings as possible?

The below code perfectly calculates the factorial of a number.

#include <stdio.h>

long int f_fact(int i);

int main() {
    int a;
    long int factorial;

    printf("Please enter a number\n");
    scanf("%d", &a);

    factorial = f_fact(a);
    printf("The factorial is %ld\n", factorial);

    return 0;
}

long int f_fact(int i) {
    int j;
    long int factorial = 1;

    for (j = 2; j <= i; ++j) {
        factorial = factorial * j;
    }
    return (factorial);
}

However, this other code doesn't. The only difference is having this for (j = 2; j <= i; ++i) instead of this for (j = 2; j <= i; ++j) .

#include <stdio.h>

long int f_fact(int i);

int main() {
    int a;
    long int factorial;

    printf("Please enter a number\n");
    scanf("%d", &a);

    factorial = f_fact(a);
    printf("The factorial is %ld\n", factorial);

    return 0;
}

long int f_fact(int i) {
    int j;
    long int factorial = 1;

    for (j = 2; j <= i; ++i) {
        factorial = factorial * j;
    }
    return (factorial);
}

My question is how can I best spot these little mistakes in the code? Right now, I have -Wall and -Wextra activated, but even with those I am getting: Errors: 0 and Warnings: 0 which makes it a bit harder to spot the issue. Any recommendations to better work my way through bugs? Thank you!

A compiler can not check logical errors. You might have written that instruction by purpose.

Oh, to check a few more auto-detectable issues, GCC knows -pedantic , but please read the full documentation. And you might like to try clang's features.

This is the field where unit-testing comes into play. Start with a good book, try some frameworks, and then test your logic.

" My question is how can I best spot these little mistakes in the code? "

Unfortunately, there are no compiler options to detect logical issues, neither in GCC nor Clang.

Using a misplaced object in a place where an object of the same type can be inserted is impossible for a compiler to detect because this is a logical issue. A compiler is only be able to detect syntactic issues.

If no memory suppose to be corrupted, it can´t even be found by some additional code analyzer tools like fe AddressSanitizer or Valgrind.

The only thing you can do to prevent such mistakes is that you have to be careful at coding.

Avoid to copy & paste too often and rather have a clear focus by writing code parts separately.

With regard to the provided issue, Avoid copying loop heads or parts of it, especially inside of nested loops.


But to answer your question:

Apart from -Wall and -Wextra what other tools are available to spot as many errors or warnings as possible?

There are -Wpedantic / -pedantic , -Wall and -Werror for GCC for example.

You can find them and more, listed with their according explanations, here:

https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#Warning-Options


For Clang you have fe -Weverything . You can find the list of diagnostic options with their descriptions here:

https://clang.llvm.org/docs/DiagnosticsReference.html

You already know and use -Wall -Wextra , which can be completed with -Werror to detect potential mistakes by flagging a number of classic problems.

While you can add more compiler options to try and detect other problems, yet it is difficult to detect logic errors. Simple typos can be detected if for example a variable is set but not used, but your mistake would still go unnoticed.

Other precautions include coding style and naming conventions: very strict style rules, especially the consistent use of spaces and indentation, help make the code more readable and give less space for silly bugs to hide. Naming conventions help too: in your example, one should not name the argument i , but rather n . i is the default name for an index variable, as you experienced yourself, so naming the argument correctly would effectively have prevented this mistake:

long int f_fact(int n) {
    long int factorial = 1;

    for (int i = 2; i <= n; i++) {
        factorial *= i;
    }
    return factorial;
}

Here are some extra flags I use for my projects in addition to -Wall -Wextra (and -Weverything for clang):

  • avoid problems with potentially signed char type: -funsigned_char -Wchar-subscripts
  • prevent printf with variable format strings: -Wformat-nonliteral
  • make string literals const : -Wwrite-strings

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM