Compiler, Linker and Run-Time Errors


There are many types of programming errors. This tutorial discusses the general categories under which those errors fall:

  1. Compiler Messages
  2. Linker Errors
  3. Run-Time Errors
Note that the error messages shown below may be specific to our compiler/linker or machines. Nonetheless, other systems and compilers will provide similar information.


Compiler Messages

When the compiler is compiling your code (i.e., converting your code into instructions the machine understands), it will report problems that it finds in your code.


Aside: Here, we are being technical and refer to compiling as the stage before linking. Linking is when all the compiled pieces of a program and the libraries it uses (e.g., for cin) are put together to form an executable. Often, compiling and linking together are just referred to as compiling.

There are two severities of messages the compiler can give:

  1. Compiler Warnings

    A compiler warning indicates you've done something bad, but not something that will prevent the code from being compiled.

    You should fix whatever causes warnings since they often lead to other problems that will not be so easy to find.

    Example: Your code calls the pow() (raise to a power) library function, but you forgot to include math.h.

    Because you've supplied no prototype for the pow() function (its in math.h), the compiler warns you that it assumes pow() returns an int and that it assumes nothing about pow()'s parameters:

    somefile.cpp:6: warning:
      implicit declaration of function `int pow(...)'
    

    This is a problem since pow() actually returns a double. In addition, the compiler can't type-check (and possibly convert) values passed to pow() if it doesn't know how many and what type those parameters are supposed to be.


    Note: The compiler will label warnings with the word warning so that you can distinguish them from errors.

  2. Compiler Errors

    A compiler error indicates something that must be fixed before the code can be compiled.

    Example: You forget a semi-colon (;) at the end of a statement and the compiler reports:

    somefile.cpp:24: parse error before `something'
    


    Always remember to fix the first few errors or warnings, since they may be causing all the rest.

    Compiler messages usually list the file and line number where a problem occurs. Nonetheless, errors often occur on the lines prior to what the error message lists. Especially check the line immediately preceding where the error message indicates.

    Finally, note that some compilers may choose to call something an error while others may just call it a warning or not complain at all.


    Linker Errors

    If you receive a linker error, it means that your code compiles fine, but that some function or library that is needed cannot be found. This occurs in what we call the linking stage and will prevent an executable from being generated. Many compilers do both the compiling and this linking stage.

    Example 1: You misspell the name of a function (or method) when you declare, define or call it:

    void Foo();
    
    int main()
    {
      Foo();
      return 0;
    }
    
    void foo()
    {
      // do something
    }
    

    so that the linker complains:

    somefile.o(address): undefined reference to `Foo(void)'
    

    that it can't find it.

    Example 2: You use the X Windows XDrawLine() function (and include the header file for it), but forget to use the -lX11 option to tell the linker to use the X Windows library. It will complain that it doesn't know about the XDrawLine() function:

    somefile.o(address): undefined reference to `XDrawLine'
    


    Run-Time Errors

    Run-time errors only occur when you run a program, and thus, they can only occur if there is a program to run (i.e., it must have compiled and linked without errors). When you run the executable and something goes wrong then we call it a run-time error. There are two main types of run-time errors:
    1. Fatal Errors

      A fatal error is basically when the executable crashes.

      Example 1: The program divided by zero, as in:

      int scores = 500;
      int num = 0;
      int avg;
      avg = scores / num;
      

      The program would crash saying:

      Floating exception
      

      Example 2: Segmentation faults, Bus errors.

      These occur when you try to access memory that your program is not allowed to use or that doesn't exist in the computer (i.e., there is only so much memory in the computer).


      Aside: Even virtual memory has limits.

      Your program will crash giving the "Segmentation fault" or "Bus error" message.

      These errors often occur due to improper use of arrays or pointers.

      Example: Using an uninitialized array index...

      int values[10];
      int i;
      cout << "The ith value is: " << values[i] << endl;
      
      may cause such an error. These, particularly, are tricky since they may or may not occur based on what the initial garbage value of the index is when you run the program. Remember, you cannot generally assume variables get initialized to zero.

    2. Logic Errors

      A logic error occurs when your program simply doesn't do what you want it to.

      Example: You have an infinite loop because you did not update the variable(s) used in the condition of a loop, as in:

      cin >> account_num;
      
      Assume user did not enter -1.
      
      while (account_num != -1) {
        cout << "Account #: " << account_num << endl;
        ProcessAccount(account_num);
        // Oops...Forgot to read another account # here!
      }
      


    There are two general techniques for finding the cause of a run-time error:

    Both techniques can be applied either with or without a debugging utility.


    BU CAS CS - Compiler, Linker and Run-Time Errors
    Copyright © 1993-2000 by Robert I. Pitts <rip at bu dot edu>. All Rights Reserved.