Previous Section Table of Contents Next Section

Syntax Versus Semantics

Most writing on programming errors distinguishes between two basic types of errors: syntax errors and semantic errors.

Syntax errors involve the precise definition of how valid programs are formed. For example, in Python, the following code fragment


if i == 5


is syntactically incorrect because Python syntax specifies that an if statement must have a colon at the end of the line.

This book does not deal with syntax errors. Spotting them can involve more detailed knowledge of the language than what this book requires. More importantly, they won't sneak in unnoticed; when a compiler or interpreter encounters a syntax error, it reports an error to the user. Although one single syntax error can often cause a cascade of related errors, which makes it difficult to figure out where the actual error is (for example, if the declaration of a variable is incorrect, every reference to it might become a syntax error), it is still apparent that something is wrong and needs to be fixed.

Note

Arguably, another class of errors exists: Linker errors, where the compiler cannot produce a binary, can occur when an external variable or function name has a typo, or if there is a problem with how the compiler is installed, or for various other reasons that are outside the scope of this book. Because these errors are language- and system-specific, and (like syntax errors) result in an error being reported to the user, this book does not worry about linker errors.


What this book focuses on is semantic errors.

Semantic errors can be broken down into runtime errors and logic errors. Runtime errors cause the program to crash or abort in some way, while logic errors cause a program to run to completion, but produce the incorrect output or result.

This book does not distinguish between those two types of semantic errors. It is often pure luck whether a buggy program exhibits one misbehavior or the other. A runtime error leading to a crash could be considered a form of "bad output," and a program that has a logic error might run to completion on some inputs, while crashing with an error on others. For example, the following code fragment


int compute_average(int array[], int count) {

    int j, total = 0;

    for (j = 0; j < count; j++) {

        total += array[j]);

    }

    return total / count;

}


works correctly on most inputs, but crashes with a divide by zero error if count is 0. (It's debatable what the program should do in such a case, but crashing is not the answer.) Meanwhile, in some languages, certain bugs always cause a runtime error (using an incorrect array index is one example), but in others, they usually result in silent logic errors. So, the book won't try to distinguish between runtime and logic errors.

    Previous Section Table of Contents Next Section