COMMON ERRORS IN C++ PROGRAMS ============================= This file explains some compiler messages you might get in either C or C++. If you don't know C++, ignore items which talk about "class", "constructor", "object", "instance", or "method". Compiler errors and warnings ---------------------------- `NULL' undeclared (first use this function) Add #include at the top of your file return type specification for constructor/destructor invalid Structure and class definitions must end with a semicolon. It's likely that your .h file contains a semicolonless structure or class definition, and the beginning of the next file contains the constructor or destructor. g++ sees a type (the structure or class) immediately followed by a function, so it thinks you're trying to define the return type of your constructor or destructor, just as if you had said int item::~item() { ... } control reaches end of non-void function You have declared some function to return a value of a particular type (its return type isn't void), but the compiler thinks that the function could be executed without encountering a return statement at all. For instance, maybe you have something like int blibble(char *, tray *) { if (foo) return bar; if (baz) return quux; } The compiler is warning you that if foo is false, and baz is false, then this function doesn't return an int, as you've promised it will. You might want to see whether that can happen in real life. If so, maybe you need to rethink the logic of the function. If not, then maybe you can remove a test. Maybe baz is always true if foo isn't, so you could use if (foo) return bar; else // baz is true return quux; and save a test of baz. As a last resort, you can just trick the compiler by adding one or more appropriate "else" clauses which are never executed but which return something of the correct type. if (foo) return bar; if (baz) return quux; else { cerr << "This can't happen!" << endl; return 0; } void value not ignored as it ought to be Declaring a function to return type void means the function doesn't return anything at all -- it is only called for side effect, never for value. (Speaking of the void value doesn't make sense -- just as there are exactly two values of type bool, there are zero values of type void.) But you have tried to use the return value of a function with void return type. void foo(); // declaration cout << foo(); // erroneous use multiple definitions Sometimes "multiple definition" errors are caused by your failure to declare a constructor/destructor in a class -- which causes C++ to automatically create one for you -- followed by definition of one outside the class. So there are two of them: the one C++ created because you didn't say you were going to define it yourself, and the one that you defined. no conversion from `base' to type with default `operator <<' The system said, "I don't know how to apply "operator <<" to a base, but can I convert a base into something that I do know how to output?" It tried, but of course we can't convert any old base type object into one of a derived type (we can't convert any old bird into a robin), so it failed. Internal compiler error. This should never happen (but, sadly, does). If it does happen, then there is most likely a problem somewhere in your code. Save a copy of your files in a safe place and tell the instructor so a bug report can be submitted; then you must find your problem by hand (or have a friend or staff member help). Linker errors and warnings -------------------------- Recall that compilation happens in two steps: * convert .cc files to .o files * link together .o files (plus libraries) into an executable This section describes problems in the second setp. The linking program is named "ld", and it is called by a program named "collect2", which is called by g++ to do linking. ld: /lib/libc.sa.1.9: warning: table of contents for archive is out of date; rerun ranlib(1) This is a problem with the C/C++ library. Compile on a different machine, and send mail to problem@rice.edu telling them the name of the machine you were using and the version of the compiler. ld: Undefined symbol stack::stack(void) stack::pop(void) stack::push(char *) You failed to link in the definitions of stack::pop, stack::stack, and stack::push. Remember tutorial 3: if you use the -o flag to g++, you are saying, "I am supplying the entire program; please name the executable according to the -o flag." You may also see "mangled" names like pop__5stack, which the c++filt or g++filt programs can translate back into names like stack::pop; but you can usually tell what is going on just by eyeballing the mangled name. ld: Undefined symbol __$_6t_tree You failed to link in the defintion of t_tree::~t_tree (the destructor for t_tree). To get this information, run the g++filt program and type (or paste) the name __$_6t_tree to standard input; g++filt responds with "t_tree::~t_tree()". More recnet versions of g++ automatically unmangle names before you see them, so you may never get this kind of error or need to use g++filt. C++ uses "mangled names" such as __$_6t_tree because overloading permits many functions of the same name, but many tools (such as linkers) permit only one definition per name. mangled names are guaranteed to be unique. ld: Undefined symbol _cout ostream::operator<<(char) ios::operator void *(void) const _cin istream::operator>>(char *) You may have compiled using the gcc compiler, which only understands the C language. Use the g++ compiler to compile C++ programs. ld: Undefined symbol _sqrt You need #include so the compiler knows that sqrt will exist; contains a declaration for that function (and others). Your final program needs the definition of sqrt as well. To make that available to the linker, add -lm (which means "include the math libraries") to your linker flags. Be sure to put this at the end of the link line. ld: Undefined symbol ___8ifstreamiPCcii _eof__C3ios _sqrt _endl__FR7ostream ___ls__7ostreamPFR7ostream_R7ostream ___opPv__C3ios ___ls__7ostreami ___ls__7ostreamPCc _cerr _get__7istreamRc ___8ofstreamiPCcii _close__11fstreambase ___nt__C3ios You should have put -lm at the *end* of the link line. ld: fatal: file foo.o: unknown type, unable to process using elf(3E) libraries You have compiled foo.cc into foo.o on a SunOS 4.x machine, but you are trying to link foo.o with other object files on a machine running the Solaris operating system. Remove all the object files (do "make clean") and recompile from scratch. ld: foo.o: premature EOF Perhaps compilation of foo.cc into foo.o was terminated unexpectedly, resulting in an incomplete foo.o file. Check your quota, remove foo.o, and try compiling again. Other build-time errors and warnings ------------------------------------ Makefile: *** missing separator. make: Fatal error in reader: Makefile, line 6: Unexpected end of line seen (This is a problem with your Makefile, not with your C++ program.) Makefile command lines must start with a tab character, not with spaces. Using spaces instead will cause these and a number of other errors in make. make: *** No rule to make target `/usr/include/sys/stdtypes.h', needed by `main.o'. make: Fatal error: Don't know how to make target `/usr/include/sys/feature_tests.h' Running "makedepend" has inserted dependences on system files in your Makefile. Now you are trying to make on a different operating system which stores the system files in different places. (For instance, you ran "makedepend" on SunOS 4.x but are running "make" on Solaris.) Run "makedepend" again, and then "make" should work. make: Fatal error in reader: Makefile, line 37: Unexpected end of line seen Don't put blank lines in the middle of the command section of a rule; commands must immediately follow one another (and must each be preceded by a TAB character on its own line). out of disk space / quota exceeded. This has nothing to do with the compiler per se, but occurs frequently when running the compiler. You need to remove some files; concentrate on the big files. Use the du command (issued in your top-level directory) to determine the disk usage of each of your directories. (The du output will show all disk usage in your home directory, but you might also own some files in other directories, including the mail spool directory. "quota -v" tells you how much space all your files are taking up, albeit not where the files lie.) Likely candidates include: * executables. g++ can produce quite large ones, so delete them if you no longer need them, but be sure to keep the source, which is quite small by comparison, so you can recreate the executables when need be. * the contents of your .netscape-cache directory, which often contains bulky images. It is always harmless to delete the contents of this directory, either directly \rm -rf ./netscape-cache/* or in Netscape (Options - Preferences - Cache and Network - Clear Disk Cache Now). * core files. Named "core", these contain the full state of the system when a segmentation fault or other early termination occurred. They can be useful for debugging (GDB can read them), but if you aren't going to use it right away, get rid of it. You can put "set coredumpsize=0" in your .cshrc to prevent core files from ever being created. Also consider compressing infrequently-used files with the compress or gzip programs. To compress file foo, just do "compress foo" or "gzip foo" (gzip is slightly more effective), which removes file foo and creates foo.Z or foo.gz (respectively). Use "uncompress foo.Z" or "gunzip foo.gz" to get back file foo. If you can't clear enough space, or if deleting files doesn't immediately work (sometimes it takes a little while for the system to notice you're back under quota), then you can work in /tmp. Create a subdirectory for yourself ("mkdir /tmp/foo", where foo is your username), then copy your files there. This is very much a temporary solution. To request more disk quota from Owlnet, fill out the form at http://problem.rice.edu/Forms/quota.html turnin: tar failed (616) Don't try to run turnin212 or returnin212 on Solaris machines. Common run-time errors ---------------------- "Segmentation fault" or "Bus error" These errors happen when you try to access a memory location using an invalid (illegal) address. Invalid addresses are often due to uninitialized, incorrectly initialized, or deleted pointers, or indices that run beyond array bounds. Segmentation faults generally result from an attempt to access memory that doesn't belong to you (it belongs to another user or to the system, or it doesn't physically exist), while bus errors often result from misaligned pointers (for instance, pointers to integers must be divisible by 4, because all integers are laid out in memory on four-byte boundaries). A segmentation fault in a system procedure (such as nowalgnd) is almost certainly evidence that your program has corrupted memory; the system procedure has stumbled across the corrupted data structures. Infinite loops Failure to terminate (running forever) is often due to a bad loop termination condition or a bad (or missing) loop advancing statement. Make sure progress is made toward the termination condition within the body of the loop (or the third part of the for statement). Memory errors: "virtual memory exceeded" Running out of memory is usually due to memory leaks. Memory leaks occur when you fail to deallocate memory that was dynamically allocated using new or malloc. A memory leak is an error even if the program containing it produces the right answer for some inputs. You could also encounter this error when dynamically allocating many objects, since Owlnet processes are limited to 4MB of memory usage. If you get this with a small input file, be sure you are not accidentally creating more objects that you intended. This error message also sometimes results from trying to use an istream that has already been closed. equality testing vs. assignment It's easy to confuse '=' and '=='. For example, instead of writing if (x == 5) ... you may write if (x = 5) ... The "x = 5" expression sets the value of x; the value of the expression is 5. When 5 is converted to a boolean, it becomes "true", so the then part of the if statement is always executed. If you use the -Wall flag to g++ version 2.7 or later, it will warn you about this condition in certain circumstances, saying: warning: suggest parentheses around assignment used as truth value (You can suppress the warning by putting an extra set of parentheses around the assignment: "if ((x = 5)) ...".) One quick and dirty habit for avoiding this mistake is to use the '==' operator asymmetrically: if (5 == x) ... Then, if you omit an = by mistake, the compiler will report it as an error, because "5 = x" isn't meaningful in C++ (5 cannot be an lvalue).