17 Common C Segmentation Fault Pitfalls and How to Avoid Them
This article walks through seventeen classic C programming mistakes that cause segmentation faults—such as null pointers, out‑of‑bounds array access, wild pointers, double frees, and format string bugs—and provides safe, production‑ready code examples to prevent each crash.
Pitfall 1: Null Pointer Dereference
Dereferencing a NULL pointer causes an immediate segmentation fault.
#include <stdio.h>
int main(){
int *ptr = NULL;
if (ptr != NULL) {
*ptr = 100;
} else {
printf("Pointer is null, cannot dereference!
");
}
return 0;
}Pitfall 2: Array Out‑of‑Bounds
Accessing an index outside the declared range corrupts memory.
#include <stdio.h>
int main(){
int arr[5] = {1,2,3,4,5};
int index = 2;
if (index >= 0 && index < 5) {
printf("Safe access: %d
", arr[index]);
} else {
printf("Index %d out of range!
", index);
}
return 0;
}Pitfall 3: Wild Pointer
A pointer that is never initialized points to random memory.
#include <stdio.h>
int main(){
int value = 10;
int *ptr = &value; // points to a valid object
printf("Safe operation: %d
", *ptr);
*ptr = 42;
printf("After change: %d
", *ptr);
return 0;
}Pitfall 4: Use‑After‑Free (Dangling Pointer)
Freeing memory and then continuing to use the pointer leads to undefined behavior.
#include <stdio.h>
#include <stdlib.h>
int main(){
int *ptr = malloc(sizeof(int));
*ptr = 100;
printf("Before free: %d
", *ptr);
free(ptr);
ptr = NULL; // immediately nullify
if (ptr != NULL) {
printf("Will not run
");
} else {
printf("Pointer is null, cannot use!
");
}
return 0;
}Pitfall 5: Unbounded Recursion (Stack Overflow)
Recursive functions without a proper base case exhaust the stack.
#include <stdio.h>
int safeRecursion(int n){
if (n <= 0) return 1; // base case
printf("Recursion depth: %d
", n);
return n * safeRecursion(n-1);
}
int main(){
int result = safeRecursion(5);
printf("Result: %d
", result);
return 0;
}Pitfall 6: String Copy Overflow
Copying a longer string into a too‑small buffer overruns memory.
#include <stdio.h>
#include <string.h>
int main(){
char str[20] = "Hi";
printf("Original: %s
", str);
if (strlen("Hello World!") < sizeof(str)) {
strcpy(str, "Hello World!");
printf("After copy: %s
", str);
} else {
printf("String too long to copy!
");
}
return 0;
}Pitfall 7: Returning Address of a Local Variable
Returning a pointer to a stack‑allocated variable leaves a dangling reference.
#include <stdio.h>
#include <stdlib.h>
int* getSafePointer(){
int *ptr = malloc(sizeof(int));
*ptr = 42;
return ptr;
}
int main(){
int *ptr = getSafePointer();
printf("Safe value: %d
", *ptr);
free(ptr);
ptr = NULL;
return 0;
}Pitfall 8: Double Free
Freeing the same memory block twice corrupts the allocator's metadata.
#include <stdio.h>
#include <stdlib.h>
int main(){
int *ptr = malloc(sizeof(int));
*ptr = 100;
printf("Using memory: %d
", *ptr);
if (ptr != NULL) {
free(ptr);
ptr = NULL;
}
if (ptr != NULL) {
free(ptr); // will not execute
} else {
printf("Pointer already null, no need to free
");
}
return 0;
}Pitfall 9: Format String Vulnerability
Passing user‑controlled data directly as a format string lets attackers read/write arbitrary memory.
#include <stdio.h>
int main(){
char userInput[] = "Name: %s, Age: %s, City: %s, Job: %s";
printf("%s
", userInput); // treat as plain data
return 0;
}Pitfall 10: Ignoring malloc Return Value
Assuming malloc always succeeds can lead to dereferencing a NULL pointer.
#include <stdio.h>
#include <stdlib.h>
int main(){
int *ptr = malloc(sizeof(int));
if (ptr == NULL) {
printf("Memory allocation failed!
");
return 1;
}
*ptr = 100;
printf("Value: %d
", *ptr);
free(ptr);
return 0;
}Pitfall 11: Mis‑managed 2‑D Array Pointers
Allocating only the pointer array without allocating each row leaves dangling pointers.
#include <stdio.h>
#include <stdlib.h>
int main(){
int rows = 3, cols = 4;
int **matrix = malloc(rows * sizeof(int*));
for (int i = 0; i < rows; i++) {
matrix[i] = malloc(cols * sizeof(int));
}
matrix[0][0] = 10;
printf("Safe assign: %d
", matrix[0][0]);
for (int i = 0; i < rows; i++) free(matrix[i]);
free(matrix);
return 0;
}Pitfall 12: Uninitialized Struct Pointer Member
Using a struct field that points to unallocated memory causes crashes.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Student{ char *name; int age; };
int main(){
struct Student stu;
stu.age = 18;
stu.name = malloc(20 * sizeof(char));
strcpy(stu.name, "小明");
printf("Student: %s, %d
", stu.name, stu.age);
free(stu.name);
return 0;
}Pitfall 13: Pointer Parameter Mis‑use
Assigning memory to a pointer parameter without passing its address leaves the caller's pointer unchanged.
#include <stdio.h>
#include <stdlib.h>
void allocateMemory(int **ptr){
*ptr = malloc(sizeof(int));
**ptr = 100;
}
int main(){
int *myPtr = NULL;
allocateMemory(&myPtr);
printf("Value: %d
", *myPtr);
free(myPtr);
return 0;
}Pitfall 14: Modifying String Literals
String literals reside in read‑only memory; attempting to modify them causes a fault.
#include <stdio.h>
int main(){
char str[] = "Hello"; // mutable copy
printf("Original: %s
", str);
str[0] = 'h';
printf("Modified: %s
", str);
return 0;
}Pitfall 15: Unsafe Union Usage
Writing to one union member overwrites the others, leading to garbage values.
#include <stdio.h>
enum DataType{ TYPE_INT, TYPE_FLOAT, TYPE_STRING };
struct SafeData{ enum DataType type; union{ int intVal; float floatVal; char *strVal; } value; };
int main(){
struct SafeData data;
data.type = TYPE_STRING;
data.value.strVal = "Hello";
if (data.type == TYPE_STRING) printf("String: %s
", data.value.strVal);
data.type = TYPE_INT;
data.value.intVal = 100;
if (data.type == TYPE_INT) printf("Int: %d
", data.value.intVal);
return 0;
}Pitfall 16: Null Function Pointer Call
Calling a function pointer that is still NULL triggers a crash.
#include <stdio.h>
#include <stdlib.h>
void sayHello(){ printf("Hello!
"); }
void sayGoodbye(){ printf("Goodbye!
"); }
int main(){
void (*funcPtr)() = NULL;
if (rand() % 2 == 0) funcPtr = sayHello; else funcPtr = sayGoodbye;
if (funcPtr != NULL) funcPtr();
else printf("Function pointer is null, cannot call!
");
return 0;
}Pitfall 17: Race Condition in Multithreaded Code
One thread may free memory while another still accesses it, causing a segmentation fault.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
int *global_ptr = NULL;
void* thread_func(void* arg){
if (global_ptr != NULL) {
sleep(1); // simulate work
*global_ptr = 100;
printf("Set value successfully: %d
", *global_ptr);
}
return NULL;
}
int main(){
pthread_t thread;
global_ptr = malloc(sizeof(int));
pthread_create(&thread, NULL, thread_func, NULL);
pthread_join(thread, NULL); // wait before freeing
free(global_ptr);
global_ptr = NULL;
return 0;
}Ultimate Cheat Sheet
Memory Management Golden Rules
malloc must be paired with free – always release what you allocate.
Set pointer to NULL after free – prevents accidental reuse.
Check pointers before use – guard against NULL dereference.
Watch boundaries – never read or write past array limits.
Pointer Usage Mantra
Initialize – give every pointer a known value at declaration.
Validate – test for NULL before dereferencing.
Protect – respect array bounds and memory permissions.
Clean up – free and nullify when done.
Advanced Tips
Use unions cautiously – keep track of the active member.
Check function pointers – never call a NULL pointer.
Lock shared resources in multithreaded programs.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Liangxu Linux
Liangxu, a self‑taught IT professional now working as a Linux development engineer at a Fortune 500 multinational, shares extensive Linux knowledge—fundamentals, applications, tools, plus Git, databases, Raspberry Pi, etc. (Reply “Linux” to receive essential resources.)
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
