C++ ERROR MESSAGES AND WHAT THEY MIGHT MEAN by Gary T. Leavens Department of Computer Science, Iowa State University $Date: 1995/04/03 17:39:05 $ The following is an attempt to explain what the error messages that C++ produces might mean. Of course, to really understand what the error messages mean, you would have to know what the error is that you made, but then, that is what you are trying to find out! To help, this note gives an example that causes each error; you will have to look for an analogous error in your code. 1. KINDS OF ERRORS: COMPILE-TIME, LINK-TIME, and RUN-TIME There are (at least!) three kinds of errors and warning messages you may get from C++. Compile-time errors occur when you give your program to the C++ compiler, and it finds something wrong. A typical compile-time error message (from g++) is the following, which says that a semicolon (;) is missing. test.C:5: semicolon missing after declaration of `class foo' test.C: In function `int main()': Link-time errors occur when you bring separately-compiled pieces of your program together, and try to produce an executable. This also happens at the end of a call to the compiler, if you don't use the -c flag. A typical link_time error message (with g++) is the following, which says that a function named bar (taking one argument of type double, and returning an int) can't be found. /bin/ld: Unsatisfied symbols: bar__Fd (code) collect2: ld returned 1 exit status Run-time errors occur when you are executing your linked program. A typical run-time error message is the following, which could mean a lot of different things, none of them good. Bus error, core dumped. 1. HOW TO READ A COMPILE-TIME ERROR MESSAGE Let's consider the typical C++ error message test.C:7: semicolon missing after declaration of `class foo' This has several parts, separated by colons (:). The first part gives the name of the file in which the error occurred, in this case, ``test.C''. The second part gives a line number in the file. This line number is approximately where the error occurred, although often the place you have to correct the program may be a line before or after that, or even (in cases such as a missing declaration), many lines away. However, it's useful to edit the file, and look at the line named. After this comes the error message proper, which in this case is very specific: ``semicolon missing after declaration of `class foo'.'' For errors that occur within a C++ function, the compiler will given an error message something like the following. test.C: In function `int main()': test.C:10: parse error before `}' This says that in file, test.C, in the function with interface `int main()', on line 10 there is a ``parse error''. In this case the problem is the same as before: the program was missing a semicolon (;) on line 9. 2. HOW TO READ A LINK-TIME ERROR MESSAGE Consider the following link-time error message. /bin/ld: Unsatisfied symbols: bar__Fd (code) collect2: ld returned 1 exit status Symbols listed in such messages are a combination of underbars, a name you actually typed, and some coding of other interface information. Often, you can pick out the name you want from the other stuff. In the example above, it is ``bar''. (This is a good reason to name your functions and classes with descriptive names, not with names like ``Fd''.) Let's look at the message above. The ``/bin/ld: '' tells you it's an error from the linker (named ld, which originally meant a linking *loader*). That's on every link-time message, and only serves to distinguish it from a compile-time message. Following the colon is the real message. This is usually, as above, ``Unsatisfied symbols''. The second line (and subsequent similarly indented lines), tell you the ``mangled'' names of the function (or class, etc.) that you are missing. Name mangling means adding information about the number of arguments and their types to a name, which is how C++ checks for type-correctness across separate compilation boundaries. In this case the name is ``bar'', and it is a function (perhaps the meaning of the ``F'' in the mangled name) that takes an argument of type double (perhaps the meaning of the ``d'' in the mangled name) and returns an int. Object files containing these names, with the correct number and types of arguments fo functions, need to be included when linking your program (i.e., when using g++ with the -o flag). The last line is a message from another part of g++, ``collect2,'' which says that the link failed (as if you didn't already know that). An exit status of 1 means the call to /bin/ld failed. Instead of trying to unmangle a name yourself, you can use the program c++filt to do it for you. They way to run it is to invoke it without arguments, then type to it the name to unmangle. For example, here is a session with c++filt (the comments on the right were not typed). The program does not prompt one for input, it just waits, then echoes your input after ``demangling'' it. Type end-of-file (Control-d) to exit the program. % c++filt bar__Fd (code) // no prompt, I typed the name bar(double) (code) // output from c++filt % // I typed end-of-file (C-d), ends it Even easier, if you use /home/cs228/public/bin/ansicpp instead of g++, the demangling is automatically taken care of for you. 3. HOW TO READ A RUN-TIME ERROR MESSAGE There isn't much to say about this, as the run time errors messages don't tell you much except that something went wrong. This list is undoubtedly incomplete. If you have an error message that you don't understand, send me mail with it and your code. If it's not in here already, I'll add it to the list. 4. EXAMPLE ERROR MESSAGES AND WHAT THEY MEAN If you run the compile and it appears to "freeze", not giving you any output at all, then use C-c (control-c) to stop it, and check to see if you have any places where a file #include's itself. For example, if you have // Vector.C #include "Vector.C" this would cause the problem. 4.1 EXAMPLE COMPILE-TIME MESSAGES Vector.C: In method `Vector::Vector()': Vector.C:18: invalid lvalue in assignment 1. You are trying to assign to a constant. const int x = 13; x = 7; 2. You are trying to assign to a function name. Suppose your class has both a data member named xCoord and a member function named xCoord. Then you will get this message if you try to assign to the data member. The solution is to rename your data members to be something different than the member function names. teststr.C: In function `int main()': teststr.C: 13: no member function `ostream::operator <<(class String (*)())' The line pointed out by the compiler is the statement cout << "s1 is: " << s1 << endl; The compiler is complaining that it doesn't have an overload of operator << for the type of s1, which it thinks is class String (*)(). This cryptic type is the type of a pointer to a zero-argument function returning a String. How did it think that was the type of s1? Well, this comes from a declaration of s1 of the form: String s1(); // error The compiler interprets this as the declaration of a function named s1. If you want to declare a string s1, and use the default constructor, what you do is write the following. String s1; // correct Moral, don't use parentheses to invoke the default constructor in a declaration. 4.2 EXAMPLE LINK-TIME MESSAGES 4.3 EXAMPLE RUN-TIME MESSAGES Bus Error 1. You dereferenced storage you haven't allocated yet int *ip; *ip = 4; 2. You dereferenced a pointer that is null, int *ip = 0; *ip = 4; 3. You dereferenced a pointer to deallocated storage int *ip = new int; *ip = 4; delete ip; *ip = 7; 4. You used an array index that is not legal int myArray[6]; myArray[6] = 7; 5. See also the problems listed below under Segmentation Fault. Segmentation fault 1. See also the problems listed above under Bus Error 2. You might have done one of the things above as the result of using an ADT improperly. For example, the following causes a segmentation fault. #include "cstack.h" int main() { CharStack theStack; while (1) { theStack.Push('a'); } } Pid 1677 received a SIGSEGV for stack growth failure. Possible causes: insufficient memory or swap space, or stack size exceeded maxssiz. Segmentation fault 1.You tried to recurse infinitely recursion int bar(double x) { bar(x); } 2. You tried to allocate an infinite amount of memory while (1) { new Foo; } 5. WHAT IF THAT DOESN'T HELP Use emacs to indent your code. (See /home/cs227/doc/running-C++.txt for details.) Look to see if any of the indentation doesn't look right. That may give you a clue. For syntax errors, compare your code to the grammar for C++ in the texts. For run-time errors, add debug printing statements to your code. Use these first to tell you where in the program the error is occurring, and then to give you information about the values of variables just before the error. Then carefully check the area of the code where the problem is, and be sure that whatever error you find explains the problem's symptoms. (Otherwise you may only find one of several errors.) Do something else for a while (get a drink, eat dinner, go to the bathroom, etc.). Often getting away from the terminal is helpful once you have enough information in your head. If none of the above works, ask a member of the course staff, but be sure to send or bring: * your error message(s), * the C++ code, and * your test case. These will help us find out what the problem is. Another thing you can do is to use the C++ debugger to get more information. See the manual page for gdb by typing man gdb for how to do that.