Runtime Errors¶
This guide covers common runtime errors in programming, their causes, and how to prevent and handle them across different programming languages.
🎯 What Are Runtime Errors?¶
Runtime errors occur during program execution, causing the program to crash, behave unexpectedly, or produce incorrect results.
Characteristics of Runtime Errors¶
- Code compiles successfully
- Errors occur during execution
- Often cause program crashes or exceptions
- Can be handled with error management techniques
🚨 Common Types of Runtime Errors¶
1. Null Pointer/Reference Errors¶
Attempting to access methods or fields of null objects.
Problem Examples¶
// Java: NullPointerException
String name = null;
int length = name.length(); // Throws NullPointerException
// Bad: No null check
public void processUser(User user) {
System.out.println(user.getName()); // NPE if user is null
}
# Python: AttributeError
name = None
print(name.upper()) # AttributeError: 'NoneType' object has no attribute 'upper'
# Bad: No null check
def process_user(user):
print(user.name) # AttributeError if user is None
// C: Segmentation fault
int* ptr = NULL;
*ptr = 42; // Segmentation fault
// Bad: No null check
void process_user(User* user) {
printf("%s\n", user->name); // Segmentation fault if user is NULL
}
Solutions¶
// Good: Null check
public void processUser(User user) {
if (user != null) {
System.out.println(user.getName());
} else {
System.out.println("User is null");
}
}
// Better: Use Optional (Java 8+)
public void processUser(User user) {
Optional.ofNullable(user)
.map(User::getName)
.ifPresentOrElse(
System.out::println,
() -> System.out.println("User is null")
);
}
# Good: Null check
def process_user(user):
if user is not None:
print(user.name)
else:
print("User is None")
# Better: Use duck typing with hasattr
def process_user(user):
if hasattr(user, 'name'):
print(user.name)
else:
print("Invalid user object")
// Good: Null check
void process_user(User* user) {
if (user != NULL) {
printf("%s\n", user->name);
} else {
printf("User is NULL\n");
}
}
2. Array Index Out of Bounds¶
Accessing array elements outside valid index range.
Problem Examples¶
// Java: ArrayIndexOutOfBoundsException
int[] numbers = {1, 2, 3};
int value = numbers[3]; // Index 3 doesn't exist (valid: 0,1,2)
// Bad: Loop with incorrect bounds
for (int i = 0; i <= numbers.length; i++) {
System.out.println(numbers[i]); // Exception when i = 3
}
# Python: IndexError
numbers = [1, 2, 3]
value = numbers[3] # IndexError: list index out of range
# Bad: Loop with incorrect bounds
for i in range(len(numbers) + 1):
print(numbers[i]) # IndexError when i = 3
// C: Undefined behavior (may crash or produce garbage)
int numbers[3] = {1, 2, 3};
int value = numbers[3]; // Out of bounds access
// Bad: Buffer overflow
char buffer[10];
strcpy(buffer, "This string is too long"); // Buffer overflow
Solutions¶
// Good: Bounds checking
public int getSafeValue(int[] arr, int index) {
if (index >= 0 && index < arr.length) {
return arr[index];
} else {
throw new IllegalArgumentException("Index out of bounds");
}
}
// Better: Use enhanced for-loop
for (int value : numbers) {
System.out.println(value); // No index access needed
}
# Good: Bounds checking
def get_safe_value(arr, index):
if 0 <= index < len(arr):
return arr[index]
else:
raise IndexError("Index out of bounds")
# Better: Use try-except
try:
value = numbers[index]
except IndexError:
print("Index out of bounds")
value = None
// Good: Bounds checking
int get_safe_value(int* arr, int size, int index) {
if (index >= 0 && index < size) {
return arr[index];
} else {
fprintf(stderr, "Index out of bounds\n");
exit(1);
}
}
// Better: Use safe string functions
char buffer[10];
strncpy(buffer, "This string is too long", sizeof(buffer) - 1);
buffer[sizeof(buffer) - 1] = '\0'; // Ensure null termination
3. Arithmetic Errors¶
Division by Zero¶
Attempting to divide by zero.
Overflow Issues¶
Integer overflow occurs when an arithmetic operation attempts to create a numeric value that is outside of the range that can be represented with a given number of bits. For example, adding two large positive numbers might result in a negative number if the result exceeds the maximum value of a signed integer.
Problem Examples¶
// Java: ArithmeticException
int result = 10 / 0; // Throws ArithmeticException
double result = 10.0 / 0.0; // Returns Infinity
# Python: ZeroDivisionError
result = 10 / 0 # ZeroDivisionError: division by zero
result = 10.0 / 0.0 # Returns inf (infinity)
Solutions¶
// Good: Check before division
public double safeDivide(int a, int b) {
if (b == 0) {
throw new IllegalArgumentException("Cannot divide by zero");
}
return (double) a / b;
}
// Better: Handle gracefully
public Optional<Double> safeDivide(int a, int b) {
if (b == 0) {
return Optional.empty();
}
return Optional.of((double) a / b);
}
# Good: Check before division
def safe_divide(a, b):
if b == 0:
raise ValueError("Cannot divide by zero")
return a / b
# Better: Handle gracefully
def safe_divide_or_none(a, b):
if b == 0:
return None
return a / b
// Good: Check before division
double safe_divide(int a, int b) {
if (b == 0) {
fprintf(stderr, "Cannot divide by zero\n");
return 0.0;
}
return (double)a / b;
}
4. Type Conversion Errors¶
Invalid type casting or conversion.
Problem Examples¶
// Java: ClassCastException
Object obj = "hello";
Integer num = (Integer) obj; // ClassCastException
// Bad: Unsafe casting
List<String> list = (List<String>) unknownObject; // May fail
# Python: ValueError or TypeError
num = int("hello") # ValueError: invalid literal for int()
# Bad: Unsafe conversion
value = "123.45"
num = int(value) # ValueError: invalid literal for int() with base 10
// C: Undefined behavior
int* ptr = (int*)malloc(sizeof(char) * 10);
*ptr = 42; // May cause issues due to wrong type
Solutions¶
// Good: Safe casting with instanceof
public Integer safeCastToInteger(Object obj) {
if (obj instanceof Integer) {
return (Integer) obj;
}
return null;
}
// Better: Use generics
public <T> T safeCast(Object obj, Class<T> type) {
if (type.isInstance(obj)) {
return type.cast(obj);
}
return null;
}
# Good: Safe conversion with try-except
def safe_int_conversion(value):
try:
return int(value)
except ValueError:
return None
# Better: Check type first
def safe_int_conversion_better(value):
if isinstance(value, (int, float)):
return int(value)
elif isinstance(value, str) and value.isdigit():
return int(value)
return None
// Good: Proper type usage
char* ptr = (char*)malloc(sizeof(char) * 10);
if (ptr != NULL) {
strcpy(ptr, "hello");
printf("%s\n", ptr);
free(ptr);
}
5. Memory Management Errors¶
Memory leaks, double free, or use-after-free.
Problem Examples¶
// C: Memory leak
void memory_leak() {
int* ptr = malloc(sizeof(int) * 100);
*ptr = 42;
// Forgot to free(ptr)!
}
// Double free
void double_free() {
int* ptr = malloc(sizeof(int));
free(ptr);
free(ptr); // Double free error
}
// Use after free
void use_after_free() {
int* ptr = malloc(sizeof(int));
free(ptr);
*ptr = 42; // Use after free
}
Solutions¶
// Good: Proper memory management
void proper_memory_management() {
int* ptr = malloc(sizeof(int) * 100);
if (ptr == NULL) {
return; // Handle allocation failure
}
*ptr = 42;
printf("%d\n", *ptr);
free(ptr); // Always free allocated memory
ptr = NULL; // Avoid dangling pointers
}
// Better: Use helper functions
void safe_free(void** ptr) {
if (ptr != NULL && *ptr != NULL) {
free(*ptr);
*ptr = NULL;
}
}
void use_safe_free() {
int* ptr = malloc(sizeof(int));
safe_free((void**)&ptr);
safe_free((void**)&ptr); // Safe to call again
}
🛠️ Error Handling Strategies¶
Exception Handling¶
// Java: Try-catch-finally
public void readFile(String filename) {
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(filename));
String line = reader.readLine();
System.out.println(line);
} catch (FileNotFoundException e) {
System.err.println("File not found: " + filename);
} catch (IOException e) {
System.err.println("Error reading file: " + e.getMessage());
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
System.err.println("Error closing file: " + e.getMessage());
}
}
}
}
# Python: Try-except-else-finally
def read_file(filename):
try:
with open(filename, 'r') as file:
content = file.read()
except FileNotFoundError:
print(f"File not found: {filename}")
return None
except IOError as e:
print(f"Error reading file: {e}")
return None
else:
return content
finally:
print("File operation completed")
Resource Management¶
// Java: Try-with-resources
public void readFile(String filename) {
try (BufferedReader reader = new BufferedReader(new FileReader(filename))) {
String line = reader.readLine();
System.out.println(line);
} catch (IOException e) {
System.err.println("Error reading file: " + e.getMessage());
}
}
# Python: Context managers
def read_file(filename):
try:
with open(filename, 'r') as file:
return file.read()
except IOError as e:
print(f"Error reading file: {e}")
return None
🔍 Debugging Runtime Errors¶
Logging and Debugging¶
// Java: Logging
import java.util.logging.Logger;
public class DebugExample {
private static final Logger logger = Logger.getLogger(DebugExample.class.getName());
public void processArray(int[] arr, int index) {
logger.info("Processing array of length " + arr.length + " at index " + index);
if (index < 0 || index >= arr.length) {
logger.severe("Index out of bounds: " + index);
throw new IllegalArgumentException("Index out of bounds");
}
int value = arr[index];
logger.info("Retrieved value: " + value);
}
}
# Python: Logging
import logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
def process_array(arr, index):
logger.info(f"Processing array of length {len(arr)} at index {index}")
if index < 0 or index >= len(arr):
logger.error(f"Index out of bounds: {index}")
raise IndexError("Index out of bounds")
value = arr[index]
logger.info(f"Retrieved value: {value}")
return value
Unit Testing¶
// Java: JUnit test for runtime errors
import org.junit.Test;
import static org.junit.Assert.*;
public class ArrayProcessorTest {
@Test(expected = IllegalArgumentException.class)
public void testIndexOutOfBounds() {
ArrayProcessor processor = new ArrayProcessor();
int[] arr = {1, 2, 3};
processor.processArray(arr, 5); // Should throw exception
}
@Test
public void testValidIndex() {
ArrayProcessor processor = new ArrayProcessor();
int[] arr = {1, 2, 3};
int result = processor.processArray(arr, 1);
assertEquals(2, result);
}
}
# Python: pytest for runtime errors
import pytest
def test_index_out_of_bounds():
processor = ArrayProcessor()
arr = [1, 2, 3]
with pytest.raises(IndexError):
processor.process_array(arr, 5)
def test_valid_index():
processor = ArrayProcessor()
arr = [1, 2, 3]
result = processor.process_array(arr, 1)
assert result == 2
📚 Related Resources¶
- Logic Errors - Errors in algorithmic thinking
- Syntax Errors - Compilation and parsing errors
- Debugging Strategies - Troubleshooting techniques
- Code Review Checklist - Prevent runtime errors
🔗 Language-Specific Runtime Errors¶
- Java Common Mistakes - Java-specific runtime issues
- Python Common Mistakes - Python-specific runtime issues
- C Common Mistakes - C-specific runtime issues
- Oracle Common Mistakes - Oracle-specific runtime issues