Error messages in C programs can be more confusing and difficult to interpret than in Java. Here is a quick guide on some common error messages you might run into, as well as some common causes for these errors!
Common Errors
Linker error
Linker errors often occur when there is an issue with the includes. You might see an error message like “linker command failed with exit code 1”. Check to make sure:
- you include all libraries containing the functions being used in the program at the top of the file
- the libraries you are including are installed properly/the path to the library is correct
- all functions declared in header files are defined in the corresponding .c files
Undefined reference to main
This type of linker error occurs when the linker is unable to find a main method. Make sure you define a main method in your program!
Implicit declaration
If you see the error message “error: implicit declaration of function xxx”, this means you are not properly declaring the function xxx. Check to make sure:
- you declare all functions before calling them
- the header file containing the declaration of the function is included at the top of the file
- there are no typos in your function calls/declarations
Segmentation fault
A segmentation fault occurs when you try to access illegal or non-existent memory. Some common causes for this error include:
- accessing an uninitialized or null pointer – you should initialize pointers to a valid address.
- forgetting a null terminator at the end of a string
heap-use-after-free
This error indicates that you are trying to access memory that has already been freed. Make sure you are not prematurely freeing objects!
heap-buffer-overflow
If you see this error, you are probably accessing memory which is out of bounds of what you have allocated. For instance, you might be accessing an array index which is out of bounds.
Memory Leaks
Memory leaks occur when you forget to free objects allocated in heap memory. As a general rule of thumb, if you malloc something, you should also be freeing it at the end of the program. In addition, if you have an array of objects, you should free all the objects within the array and then free the space allocated for the array itself as well. Make sure you are freeing everything properly!
Free(): invalid pointer
You may get this error if you try to free something which is not allocated in heap memory. In general, you should only free things which have previously been malloc’d. This means we do not want to free primitive types such as int, double, etc.
Incompatible pointer to integer conversion (warning)
In Python, strings and chars were treated the same; there is no separate char type. However, in C we represent characters using single quotes. Strings are either represented using an array of characters or as a string literal, in which we use double quotes (includes the null terminator). Trying to represent a character using double quotes will result in this error.
Double free
You may run into an AddressSanitizer error which says “attempting double-free”. This error happens when you attempt to call free() on something multiple times. Make sure everything you malloc is being freed, but only once. Watch out for objects which have pointers to each other and make sure that free() is called on each pointer a single time.
Other Potential Issues
String comparison
The built-in string.h library contains the method strcmp which compares the contents of the two strings. Just like in Java, using the == operator in this case will compare the addresses of the pointers to these strings, rather than the contents and may produce unintended results.
Null-terminating strings
As you saw in lab01, it is important that we null-terminate strings in C. If we fail to do so, the program may continue running until it happens to run into an address with a zero byte in memory and thus have unexpected behavior. Make sure to:
- leave an extra unit of memory for the null-terminator when mallocing
- explicitly set the last bit to the null-terminator
Integer overflow
One issue you might run into is a variable not holding the proper integer value you expect. For instance, using the size_t type for negative values will cause the value to overflow to a very large positive number (since size_t is unsigned). Also, make sure any decimal values are given the double type, otherwise the value will be rounded.