Can all languages have semantic and logical errors?

I have been reading about PHP and many authors mention semantic and logical errors separately. As an example of a semantic error, they give a function called with incorrect number of parameters: this will not be caught by the parser, but will throw an error when run.

Yet in languages such as C++, this will be caught by the compiler. I would say that it's a syntax error then. What is the difference then between a semantic and a logical error?

For example, in How to think like a computer scientist, the author uses "logic error" and "semantic error" interchangeably. On the other hand, in the Visual Basic .NET. Primer Plus, "logic error" is separated from "semantic error".

• Also, dup of: programmers.stackexchange.com/questions/113800/… – alfasin Aug 31 '12 at 9:29
• I know the defitions, the problem is that it does not apply to all programming languages the same way, as mentioned in the answers. I did not ask WHAT IS SEMANTIC, SYNTAX AND LOGICAL error. Some authors consider semanthic to be logic error, some do not. – user970696 Aug 31 '12 at 9:30
• Calling a function with wrong arguments is not a syntax error. It is a type-, and, therefore, a semantic error. – SK-logic Sep 3 '12 at 11:40
• Some people include static semantics (names, types, ...) in the term "syntax", effectively denoting everything that can be (or rather, is) checked by the compiler as "syntax". "Semantic" is what governs execution of the program, e.g. dynamic method dispatch. I am not aware of a formal definition of "logical error". Maybe you want to distinguish between mistake, fault and error. Logical mistakes (by the programmer) cause faults (in the program) which might cause errors (at runtime) which the compiler can not exclude (e.g. NPE, div-by-zero, ...). – Raphael Sep 12 '12 at 22:44

I think most likely the explanation for some authors using "logic error" and "semantic error" interchangeably and some authors drawing a distinction is simply that they don't have a precise universally accepted definition, and so people are using the terminology slightly differently. I wouldn't get hung up on it.

Both "logic" and "semantic" imply something to do with the meaning of the programming, so it would be easy to regard them as the same.

If I were to draw a distinction, a useful one I can see is that a logic error is when the program ends up meaning something other than what the programmer intended, and a semantic error is when the program ends up not meaning anything (consistent) at all. With those definitions, you could either regard logic errors as a superset of semantic errors, or that logic errors exclude errors that result in the program being inconsistent.

For example, the following pseudo code contains only a logic error:

x = read_number_from_user("x: ")
print("The product of x and y is: ")
print(stringify(x + y))


The meaning of this program (taken solely as-is and without considering the programmer's intent) is perfectly straightforward and consistent. But it doesn't mean what the programmer intended it to mean.

OTOH, the following pseudo code contains a semantic error:

name = read_string_from_user("What is your name?")
print(name + 1)


At least, it does if we assume that adding a string and a number doesn't mean anything. In languages like PHP it does mean something, and this wouldn't be a semantic error.

Your example of a semantic error in PHP as calling a function with an incorrect number of parameters is actually interesting, because it's debatable whether you should call that a semantic error (with the definition I'm using).

Functions are defined dynamically at runtime in PHP. So calling a function with an incorrect number of parameters could be regarded as a logic error; perhaps the wrong include statement was executed, causing a different function with the same name to be included than the one the call was supposed to go to. Even if not, calling a function with the wrong number of arguments does mean something; it means lookup the function with this name and pass it these arguments. It's only operationally at runtime that it turns out the interpreter is unable to carry out those requests; just as x / y means something, but may be impossible to carry out if y happens to be 0 at runtime.

Ultimately, how you classify errors using a distinction like the one I'm making here between logic and semantic errors (even if it's not exactly the one I'm making) depends very much on the particular language you're talking about and how you assign meaning to programs in the language. Most commonly used languages do not have a standard way of assigning meaning to their programs, which means that everyone uses a slightly different way of doing so (though everyone's interpretation would agree very closely on almost all operational effects), and would analyse the "logical" vs "semantic" distinction differently.

Another similar way of looking at it would be to say that semantic errors are whatever causes the programming language to reject the program as invalid (apart from syntactic errors, though again you could call those a subset of semantic errors if you want). If the programming language accepts the program then it means something, and if it fails at runtime then that is the result of a logic error. This is pretty much assigning the programming language implementation (interpreter, compiler + runtime system, whatever) as the definition of what programs mean.

It's possible to distinguish many categories of errors in programs based on the point at which they manifest. Some categories don't arise in certain contexts (depending on the programming language, on how the program is designed, on how the program is used…). The terminology varies a lot between communities. I'll show a typology of the main categories; keep in mind that

• there are workflows where some of these categories won't apply;
• there are workflows where it's convenient to make other distinctions;
• similar errors may end up in different categories depending on the programming language and tools that are used;
• different people have different terminologies, the names I give are plausible but by no means consensual.

You can distinguish different categories of errors based on the point at which they are noticed.

1. Syntax errors
The compiler or interpreter tells you that what you wrote doesn't even make sense. In most languages, this is a fatal error, which won't let the program even begin to be executed.
Example: a missing close parenthesis.

2. Static type errors and other compiler errors
The compiler or interpreter tells you that while it understood what you requested, that doesn't make sense. The distinction between syntax errors and other kinds of compiler errors is a matter of internal compiler design, or sometimes of the design of the programming language.
Example: using a variable that has not been defined (this is often considered a syntax error but not always)

In statically typed languages, the compiler rejects programs that attempt some kinds of invalid operations. In dynamically typed languages, such errors are runtime errors, either fatal or not. Example: trying to divide an integer by a string.

3. Startup errors
This is the first category of errors that is revealed to the person who runs the program rather than the person who makes the program.
The program won't start, or won't reach a state where it actually does something.
Example: trying to use an external library that is not present on the system.
Example: any syntax or compilation error in an interpreted language (where the programmer distributes the source code).

4. Fatal runtime errors
At some point, the program stops working.
Example: memory access violation (attempting to access memory that isn't allocated to the program)
Note that sufficiently complex programs may attempt to catch just about any error, turning them into recoverable errors.

5. Unexpected, but recoverable runtime errors
Some component of the program stops working, but the program keeps going. Example: running out of memory (if the program is designed to handle this gracefully)
Example: one process in a multiprocess application crashes, but the other processes keep running

6. Expected runtime errors
Some error condition is expected, but it has been programmed for. This is just normal behavior, reacting to an external event which is somehow “bad” but which can happen. When you consider the program as a whole, these are not really errors.
Example: network disconnection
Example: invalid user input

7. Programming errors
The program is doing something, but that's not what it's supposed to be doing according to its specification. There's a difference between what the programmer intended to do and what the source code actually means.
Example: a web application is supposed to let you upload a file, but it doesn't work on file names containg spaces; the application rejects the file and goes on working.
Example: a program designed to multiply some number returns a result, but the mathematical operation is not performed correctly.

8. Specification errors
The program is doing something, and conforms to its specification or documentation. However, upon reflection, the program's behavior in this situation is not good. (“Not good” is of course a subjective judgement.)
Example: component 1 expects a space-delimited list of file names. Component 2 sends it a single file name that contains spaces. The two components weren't carefully designed to work together.
Example: a program to predict the weather announces rain which doesn't come, because its modeling of the physical world wasn't good enough.

It is fairly typical to consider 2–4 to be semantic errors and 7–8 to be logic errors. (However, note again that the terminology can vary.) Recoverable runtime errors are not errors of the program as a whole, but may be seen as runtime errors of some part of it.

There is a different terminology that considers that

• semantic errors are what a compiler with a static type system would typically catch, or what would cause a “protective” runtime system to abort a program with an exception that is not due to an external event (e.g. method not found as opposed to file not found);
• logic errors are what would not be caught.

This can be a fairly precise distinction when you consider a specific language and a specific type checker. However, when people use these terms, they often have a very imprecise idea of what that hypothetical compiler would be. For example, if you're programming in Java, passing the wrong number of arguments is caught by the compiler. If you're programming in PHP, it's caught by the runtime system. If you're programming in Perl, it's likely to not be caught (in the absence of any argument declaration, extra arguments are ignored and missing arguments produce a default value).

Or, to give another example: suppose you have a 10-element array and you try to access the 11th. In some languages such as C, this causes your program to access some unrelated zone of memory, leading to unpredictable behavior. In other languages, this causes an exception to be thrown; depending on whether the programmer expected this, this may be a semantic error (the programmer expected that the index might be out of bounds but did not check for that situation), a logic error (the programmer mistakenly thought that the index would always be valid), or not an error at all (the programmer relied on the exception to test whether the array index was within the bounds of the array).

The moral of the story is that these classifications are highly variable. Don't attach much importance as to which errors are put into which categories by which authors. The important thing is to understand the relationship between what you write and what the program should do. As a programmer, your job is to bring the huge gap between what I write and what I mean. If something falls in the gap, don't get hung up on fitting it with a label; concentrate on understanding what is going wrong and how to fix it.

• "what you wrote doesn't even make sense" vs "that doesn't make sense" is not a very clear distinction. I think it would help to say "parsing CFG fails --> syntax error. Rest (in compiler) --> static semantics". Furthermore, I think the answer would profit from a distinction between mistake, fault and error (as I explained/defined them in my comment on the question). – Raphael Sep 13 '12 at 6:32
• The distinction of error types can be useful to choose a programming language for a given project. In some environments (security criticial systems, for example) you want as many mistakes as possible caught by the compiler, in order to provably exclude as many errors as possible. To this end, there are even compilers that understand and verify (simple) formal specifications (which would catch "logical mistakes"). – Raphael Sep 13 '12 at 6:38

Basically you have to look at the languages itself first.

PHP is an interpreter language, that means the scripts are compiled and executed every time at runtime C++ is a compiler language, that means the scripts are compiled with a compiler once at build time and can be executed then.

so both compilers recognise the semantic error from your example, but the php compiler does this at runtime, and the c++ compiler at compile time.

A good explanation for your question can be found at Wikipedia and here (difference between semantic and syntax)

• This is mistaken. Usually, PHP is compiled, too, and with an opcode cache, its compilation phase is separated from the execution phase. The real reason for the difference is that C++ uses much stronger typing and type checking than PHP. Granted, strong typing and separate compilation usually go together, but strictly speaking they don't have to. – reinierpost Nov 9 '14 at 23:09

My guess:

• A semantic(al) error is a programming mistake which produces code that is syntactically valid, but cannot possibly do what its programmer intended, no matter what that intention was. The code is definitely wrong and might be flagged as such by software tools - although software tools cannot possibly flag all such errors (by Rice's Theorem).
• A logic(al) error is a programming mistake which produces code that is syntactically valid, but doesn't do what its programmer intended, although it might have been correct if the programmer had had a different intention. The code is only wrong given the programmer's intentions; software tools cannot flag the code as wrong, the best they can do is hint at the possibility of this mistake.

A program is a text intended to express the computation of a result that answers a question about the data. For example, a sorting program will take a list of values (the data) and should compute a result which is another list of the same values, but sorted according to some comparison function.

This text is to be expressed formally in some kind of language that is (or should be) precisely defined, both regarding what constitute a legitimate program text, and how some computational meaning can be associated to this text. Such a precise definition is often abstract (possibly mathematical), and may ignore some concrete problems such as computer limitations.

But then, the language is implemented so that programs can be executed. There are again many ways of doing such an implementation, using a intepreter of the original program text, or compiling to some intermediate code (byte-code for example), then possibly interpreting this intemediate code, or compiling it further into machine code. And there could be other variations. And of course, there are many ways of writing a compiler or an interpreter, and many machines to run them on.

Furthermore there may be several formal definitions, and several implementations, hopefully consistent.

Errors can be classified in relation the structure of either or both a formal definition or/and an implementation. However you could have strange situations where errors are classified according to an old reference implementation which is no longer the one being used.

This essentially means that classification of errors is a not really a very stable topic. Furthermore, some languages may distinguish several levels of errors depending on whether something is definitely wrong (the program will not even run) or on whether you are doing something not recommended, but that will still produce some computation, that might make sense. This is even reflected in features of programming languages such as exceptions, that may or may not be recovered from.

Standard distinctions are:

Syntax errors: the text given does not conform the structure of a program text, independently of what it should mean. This may refer only to a formal language syntax, usually context-free. It may sometimes go further and include the checking some basic features such as variable declarations (if any) or type consistency, though these may also be considered as semantic errors.

Semantic or logical errors: these are errors that can be detected when actually running the program which are due to the fact that the program runs into a calculation that does not make semantic sense, such as dividing by zero, or indexing an array out-of bounds. Calling a function with the wrong number of arguments, or with arguments of the wrong type may also be considered a semantic error. In some languages, errors may actually be user-defined by means of exceptions, when they correspond to some user defined higher-level semantics for part of his program (though there are other uses of exceptions). Some of these errors are sometimes also called run-time errors as they are detected at runtime, but they should not be confused with hardware limitation errors.

Hardware limitation errors: these are errors due to the fact that the implementation is on a real machine that has limitations. For example this may be an integer too large to fit in a memory word, or lack of sufficient memory to create a data structure. These also usually detected at run-time.

Regarding semantic errors, and hardware limitation errors, it is sometimes possible to detect them before executing the program, with what is called static semantic analysis. This is often the case for declarations or uninitialized variables, or for type errors, or for division by zero and some array bound checking, but it may go much further. Static semantic analysis is also important in compilers for many optimisation techniques. There is often a separation between static and dynamic semantics. The best definition I can imagine is that static semantics concerns properties that are decidable at compile time, without the actual data. So division by zero would not be part of static semantics in general. This goes to say that some dynamic semantic errors may still be sometimes detected at compile time. The same goes for hardware limitation errors.

But every language designer or implementor has a right to classify errors as he will, unless bound by a contract or license. That may well be the case for your PHP example. And anyone may as well make a distinction between semantic and logical errors, though I would not know how to define a difference, unless possibly being told in detail about these errors. One could be used to denote error in intent (logical error) , and would not be detectable by the system.

Note that there may be other kinds of error in a program, that will not usually be detected by the system. That includes in particular inconsistencies of the program with its specification (or what I called error in intent: the user is not doing what he meant do do), or possibly errors in the specification itself. There may also be errors due to hardware limitations such as rounding errors when working with real numbers.

According to my higher computing course notes, semantic errors and logical errors are just different names for the same thing.

• Semantic errors are different from logical errors. – Juho Nov 9 '14 at 8:35
• Unfortunately, this isn't helpful. You're disagreeing with the other answers but the only explanation you offer is an appeal to authority ("My teacher says so!"). – David Richerby Nov 9 '14 at 9:07