66

A friend of my family asked me for a bit of help as he learns to program (in the C language). As we were talking, he expressed frustration about having a hard time understanding the error messages his compiler (GCC) is giving him when he makes errors. He does not understand all the terms used, and sometimes it's their combination which is beyond his comprehension. He was asking me "How come the compiler documentation doesn't include longer explanations of the error messages?" - and I didn't have a good answer for him.

I myself - as a more experienced programmer - am very rarely in this situation, but those rare occurrences do happen - some exotic error message I hadn't encountered before. I manage to get by with looking for the error message in a search engine, but apparently that doesn't always work for him - especially since the errors he encounters are more common and occur in multiple distinct cases, which he has trouble relating to his own.

So, how should a novice programmer approach the challenge of understanding compiler error messages? Specifically, with the combination of C and GCC?

  • 7
    "So, how should a novice programmer approach the challenge of understanding compiler error messages?" /sarcasm The 1st skill needed is to be able to read every bit from the compiler message, including to relate it with the very context. /sarcasm off. It rarely turns out to be a flaw, or bug in the compiler. – πάντα ῥεῖ May 18 '18 at 18:27
  • 10
    @MasonWheeler: A novice often does not choose which compiler to use when undergoing training. And GCC is a common denominator of many, many systems... – einpoklum May 18 '18 at 18:38
  • 24
    When it comes to GCC C++ template errors, I find if I stop reading after "Error <file:line>" and study the source file(s), I find the error quicker, with an added side effect of maintaining my sanity, than if I read the actual error given by GCC..... – mattnz May 19 '18 at 5:47
  • 18
    The solution is obvious: Use a compiler with less confusing output. I suggest rmcc. It prints Yes. or No. depending on if your code compiled or not. Instantly takes away the frustration from not understanding long and pointless messages! – pipe May 19 '18 at 11:39
  • 21
    C is not a good language for beginners — and you have stumbled upon one of the reasons. That being said, Clang tends to offer much better errors that might also be more appealing to beginners. – Theodoros Chatzigiannakis May 19 '18 at 14:43
164

A few useful techniques:

  • Turn on -Wall and -Werror. It might seem counterintuitive when you're struggling with deciphering error messages to create even more error messages, but the warnings are typically easier to understand and closer to the actual source of the problem, and ignoring them can lead to errors that are difficult to understand.
  • Just try to fix the first error in the list. Often errors compound on each other, leading to later error messages not really being actual errors. Fix one and recompile. You'll get better at fixing multiple error messages when you gain more experience.
  • Use the newest compiler version possible. C is an extremely stable language. Therefore, a huge part of the improvements in newer compilers isn't to add language features, but to improve the developer experience, including better error messages. Many widely-used linux distributions have very old versions of gcc by default.
  • Program incrementally. Don't try to write a ton of code before compiling. Write the shortest amount possible that will still compile. If you've only changed one line since the last time it compiled cleanly, it's a lot easier to figure out which line contains the actual problem.
  • Write unit tests. It makes you more confident to make clarifying refactoring changes when fixing compile errors.
  • 23
    A good IDE can also greatly help the experience by eg. underlining errors in red. – BlueRaja - Danny Pflughoeft May 19 '18 at 2:02
  • 86
    "Program incrementally. Don't try to write a ton of code before compiling. Write the shortest amount possible that will still compile. If you've only changed one line since the last time it compiled cleanly, it's a lot easier to figure out which line contains the actual problem." This, so much this. Also most IDEs will warn you if you write code that won't compile, and highlight the erros. – Polygnome May 19 '18 at 10:34
  • 4
    @einpoklum: don't underestimate the third option; compiler error messages have improved a lot. In a similar vein, use several compilers (e.g. gcc and clang) - catches more errors/warnings and one of them might have a better diagnostic for a specific issue than the other. – Mat May 20 '18 at 9:24
  • 19
    @einpoklum: writing things more incrementally is very spot on, especially for beginners. Heck, if you believe "short programming assignments" cannot be done incrementally, by splitting them into several small functions and implement and compile them one-by-one, you should try to improve that skill for yourself.. – Doc Brown May 20 '18 at 9:54
  • 4
    A trick that helped me: if the error message mentions Line N, check Line N-1. For example, if you're missing a semicolon on line 17, the error message will say that something in wrong with line 18. This is because the compiler was expecting a semicolon but got something else, on the next line, instead. – user2023861 May 21 '18 at 15:36
56

Your friend does not need a glossary. A glossary will not help him. What he needs is better intuition about what to do when compiler errors occur.

C compiler errors are not as intuitive as, say, C# compiler errors, for many reasons mostly having to do with the "close to the metal" nature of C. Solving compiler errors in C is not a pattern matching exercise, because the error you receive may have nothing to do with the actual problem. Unlike C# or Java, where an error message typically maps to a precise code location and problem, errors in C are likely to be numerous and far afield.

An example of this is "semicolon expected" or any number of syntax errors that indicate the parser got hung up on something (not necessarily a semicolon). Or something like "unexpected forward declaration," an error which, when I see it, invariably means that I got capitalization wrong in one of my .h files, but which does not point to the .h file as the source of the problem.

Your friend's strategy shouldn't be to pattern match this to a list of errors and solutions; it should be to understand the syntax and specification of the C language well enough to figure out what the actual problem is.

  • 17
    No. The idea is to know the language well-enough to know that you can't make an assignment to a numeric expression, but only to a variable. You don't have to know what an lvalue is at all, which is why they don't teach that in beginner courses. – Robert Harvey May 18 '18 at 18:45
  • 18
    Essentially, yes. But practically, that's not possible. I've been doing this for a very long time and I still get obscure compiler error messages every time I write a C program. I seldom bother to read those messages and try to understand them, however; instead, I look at where the error message is pointing, and because I know what the basic syntax structure of a C program is supposed to look like, I can spot the problem relatively quickly without spending time deciphering error messages. – Robert Harvey May 18 '18 at 18:50
  • 36
    To put it another way, asking for a glossary to understand compiler errors is a bit like reading the dictionary to understand the English language; that's not quite how it works. You learn and understand English by reading and writing it, not reading the dictionary. – Robert Harvey May 18 '18 at 18:54
  • 14
    [shrug] If you're not using a dictionary to merely supplement your already-existing knowledge of English, I would suggest that you're doing it wrong. The last thing I would suggest is anything that causes novice programmers to get hung up on vocabulary any more than they already are. Programmers don't need more words; they need more skill. – Robert Harvey May 18 '18 at 18:56
  • 13
    @einpoklum, a glossary is not going to help here. The description of the word 'lvalue' is likely to be either too technical for a beginner or along the lines of 'that what can be on e left-hand side of an assignment' which is just as unhelpful. – Bart van Ingen Schenau May 18 '18 at 19:30
26

A relevant technique worth mentioning is using a second compiler. Clang has invested in better error messages, for instance, but any alternative way to phrase the error can be enlightening.

This is especially so for the most complex type of errors. For instance, when you mix up two similar constructs (not unusual for beginners), compilers typically have a problem in generating the right error message. This can cause confusion when the compiler gives an error message about the incorrect usage of construct A when you actually intended construct B. A second compiler might infer that you intended B.

13

Someone made an attempt at a GCC error glossary on Wikibooks a while ago, but it looks like it never quite took off and hasn't been updated.

The "Errors" section is much further along than the "Warnings" section. It looks like it was aimed at G++, but there is still likely to be some information of use to your friend there.

12

In addition to the above answers, note that most compilers don't have comprehensive error glossaries -- these would be a lot of work to maintain as the messages themselves often change, and there are quite a a lot of them.

The best substitute for a glossary is access to the internet. Whenever the compiler produces an error you do not understand, take comfort that it is highly unlikely that you are the first to have encountered it and been confused. A quick Google of the exact message is often sufficient to give you plenty of information in easy-to-read format, often with example code very similar to your own.

Beyond that, time and familiarity with the language and the compiler is all you need. That, and the good advice given by Karl Bielefeldt.

  • 1
    I don't think it would be a lot of work to maintain. Plus, it can be added to by the public, like Stackoverflow or a Wiki, with trusted people given editor permissions. – einpoklum May 19 '18 at 8:55
  • 6
    @einpoklum Have you ever seen the PHP docs? That's what happens when you let the community take care of that stuff. – Kevin May 19 '18 at 12:37
  • 4
    Once upon a time, published (printed) manuals were the only resource available. They were usually well-enough written to provide the necessary information/guidance to solve a problem. With the evolution of the internet, nobody publishes in print anymore (if at all, it's on-line). The quality of "official" reference material (on-line or otherwise) has fallen considerably over the decades I've been programming, so the best available resource is often Google, and the most useful results often turn up in Stackoverflow. – Zenilogix May 20 '18 at 14:34
  • 2
    Even if a glossary does exist, search engines may be the best way to access them. They're also useful for spotting when you're in uncharted territory: when the only search result is the source code which defines the error message ;) – Warbo May 21 '18 at 11:16
  • 2
    In college, I once got the compiler error "Dave doesn't think this should happen. Please email him at <dave@example.com>". I emailed him and in fact I was the first one to have hit that particular error! – user1118321 May 23 '18 at 4:02
6

The C Standard uses a number of terms like "lvalue" and "object" in ways that are different from other programming languages, and compiler messages are often written in such terms. The use of terminology is inconsistent in some parts of the Standard, but anyone wanting to learn C should look at drafts of the C89, C99, and/or C11 standards as well as the rationale documents for them. Searching for e.g. "C99 draft" or "C89 rationale" should work pretty well, though you may need to make sure you get the document you're expecting. Although most compilers support the C99 Standard, it may be useful to know how it differs from the C89 Standard, and the C89 rationale may offer some historical background that later versions don't.

  • 11
    The C standard is a very dense and heavy text. A beginner has no chance of understanding it. – NieDzejkob May 19 '18 at 15:22
  • 4
    @NieDzejkob: The terminology used by compilers--which seems to be what the question is about--is derived from the Standard. While you're correct that parts of the Standard are incomprehensible (in part because it's designed by committee, and the authors don't seem to have a consistent understanding of what parts of it are supposed to mean), but anyone wanting to understand what terms like "lvalue" mean should be aware of where they came from. Further, if one wants to understand why something like x=0x1e-x yields an error, I really don't know anything other than the Standard... – supercat May 19 '18 at 15:53
  • 3
    I agree with @NieDzejkob: The C standard is not the kind of text you want to confront a newbie with. Newbies need positive hands-on experiences fast. And they need to learn new things one by one as they pop up. Reading a standard or rationale takes way too much time while completely overloading a newbie with information. – cmaster May 19 '18 at 22:15
  • 2
    @cmaster: I started with the C89 Standard ages ago, and it wasn't too bad even in the days before browsers with a handy 'find text' feature. I'll grant that later standards have gotten worse and worse. While nobody should rely upon the Standard as a sole reference, it's important to recognize the divergence between the folk wisdom about how microcomputer compilers behave, and the ways that the Standard permits low-quality behaviors to behave, so one will be prepared if one has to deal with the latter. – supercat May 19 '18 at 23:15
  • 3
    @cmaster: In any case, someone who is programming C should be aware of the Standard, and know how to consult it when needed, even if they're not going to try to read the whole thing. If one does a web search for a standard library function, for example, one may find a reference that describes one implementation's behavior in some corner cases without mentioning that, from the Standard's point of view, those corner cases invoke Undefined Behavior and other implementations might not work the same way. If one instead searches the Standard, one can avoid that problem. – supercat May 19 '18 at 23:25
5

I'm surprised no one gave the obvious answer and, I suspect, the one most often used in practice: just don't read the error messages.

The vast majority of the value of most error messages is simply that something is wrong on such and such line. Most of the time I just look at the line number and go to that line. My "reading" of the error message at that point is usually just whatever my eye catches in passing, not even a skim. If it is not immediately clear what is wrong on or near the line, then I'll actually read the message. This workflow is even better with an IDE or tooling that highlights errors on the spot, and automatically accomplishes Karl Bielefeldt's suggestion to only consider small changes.

Of course, the error messages don't always point at the appropriate line, but then they often don't point at the appropriate root cause either, so even a full understanding of the error message would be of limited help. It doesn't take long to get an idea of what error messages are more reliable about locating the proper line.

On the one hand, most errors a novice is likely to make are likely to be painfully obvious to an experienced programmer with no help from the compiler being necessary. On the other hand, they are much less likely to be so obvious to the novice (though many will be obvious, most mistakes are stupid mistakes). At this point I agree completely with Robert Harvey, the novice simply needs to become more familiar with the language. There is no avoiding this. Compiler errors that reference unfamiliar concepts or seem surprising should be seen as prompts to deepen ones knowledge of the language. Similarly for cases where the compiler is complaining but you can't see why the code is wrong.

Again, I agree with Robert Harvey that a better strategy for utilizing compiler errors is needed. I've outlined some aspects above and Robert Harvey's answer gives other aspects. It's not even clear what your friend hopes to do with such a "glossary", and it's very unlikely such a "glossary" would actually be of much use to your friend. Compiler messages are certainly not the place for an introduction to the concepts of the language1 and a "glossary" is not that much of a better place for it. Even with a lucid description of what the error message means, it's not going to tell you how to fix the problem.

1 A few languages, like Elm and Dhall (and probably Racket), as well as a few "beginner-oriented" implementations of languages do attempt to do this though. In this vein, MSalters' advice to use a different implementation is directly relevant. I personally find such things uncompelling and not quite aimed at the right problem. This is not to say that there aren't ways of making better error messages, but, to me, they tend to revolve around making the compiler's beliefs and the basis of those beliefs clearer.

4

So, how should a novice programmer approach the challenge of understanding compiler error messages? Specifically, with the combination of C and GCC?

Tell your friend to do the following when encountering an error they don't understand:

  • Remove/comment the code added since the last successful build.
  • Put small parts of it back and compile
  • Repeat until the error occurs

Compiler errors only tell you what the compiler doesn't understand about your code, not what is wrong with it. This approach takes roughly the same amount of time as Googling the error and reading some docs or a StackOverflow post, but gives a much better understanding of what it is that you're doing wrong.

Also make them compile often until they start working on projects that take minutes to build, spotting errors before adding too much other code helps a lot.

Finally, tell them to work on one thing at a time, don't work in multiple files without compiling in between, don't introduce multiple dependencies at once, etc.

4

Another technique would be for the friend to write his own glossary over time as he encounters different error messages. Often the best way to learn something is to teach it. Of course, by the time the glossary is done, he probably won't need it anymore.

My personal experience with GCC is that each error message relates to a "usual" set of mistakes. For example, when GCC says "did you forget the &" it usually means I forgot parentheses. Of course, which mistakes correspond to which error messages will depend on the programmer, another good reason for the friend to write his own glossary.

  • 1
    This document has the tremendously important side benefit that it could be put online (even if it only has 5-10 entries) and would be a great differentiator when applying for internships. – Josh Rumbut May 21 '18 at 3:15

protected by gnat May 19 '18 at 18:56

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.