8. Common Pointer Pitfalls and Best Practices
8.1 Uninitialized Pointers
WRONG:
int *ptr; // Uninitialized - contains garbage address
*ptr = 42; // DANGER! Writing to unknown memory location
// May cause segmentation fault
CORRECT:
int *ptr = NULL; // Initialize to NULL
int num = 0;
ptr = # // Assign valid address before use
*ptr = 42; // Now safe to dereference
8.2 Dangling Pointers
A dangling pointer points to memory that has been freed or is no longer valid:
WRONG:
int *ptr;
{
int num = 42;
ptr = #
} // num goes out of scope here
// ptr is now dangling - points to invalid memory
printf("%d", *ptr); // DANGER! Undefined behavior
CORRECT:
int num = 42;
int *ptr = #
// Use ptr while num is in scope
printf("%d", *ptr); // Safe
Dangling Pointer with free():
int *ptr = (int*)malloc(sizeof(int));
*ptr = 42;
free(ptr);
// ptr is now dangling
printf("%d", *ptr); // DANGER! Undefined behavior
// Better:
free(ptr);
ptr = NULL; // Set to NULL after freeing
if (ptr != NULL) {
printf("%d", *ptr); // This check prevents the error
}
8.3 NULL Pointer Dereference
WRONG:
int *ptr = NULL;
*ptr = 42; // CRASH! Cannot dereference NULL pointer
CORRECT:
int *ptr = NULL;
if (ptr != NULL) { // Always check before dereferencing
*ptr = 42;
} else {
printf("Error: NULL pointer\n");
}
8.4 Array Bounds with Pointers
WRONG:
int arr[5] = {1, 2, 3, 4, 5};
int *ptr = arr;
int value = *(ptr + 10); // Out of bounds! Undefined behavior
CORRECT:
int arr[5] = {1, 2, 3, 4, 5};
int *ptr = arr;
int size = 5;
for (int i = 0; i < size; i++) {
printf("%d ", *(ptr + i)); // Safe: within bounds
}
8.5 Returning Pointer to Local Variable
WRONG:
int* createNumber() {
int num = 42;
return # // DANGER! num is destroyed after function returns
}
int main() {
int *ptr = createNumber();
printf("%d", *ptr); // Undefined behavior - dangling pointer
return 0;
}
CORRECT - Using Dynamic Allocation:
int* createNumber() {
int *num = (int*)malloc(sizeof(int));
*num = 42;
return num; // Safe - memory persists
}
int main() {
int *ptr = createNumber();
printf("%d", *ptr);
free(ptr); // Don't forget to free!
return 0;
}
CORRECT - Using Static Variable:
int* createNumber() {
static int num = 42; // Static - persists after function returns
return #
}
8.6 Best Practices Summary
-
Always initialize pointers
int *ptr = NULL; // Good int *ptr; // Bad
-
Check for NULL before dereferencing
if (ptr != NULL) { *ptr = value; }
-
Set pointers to NULL after freeing
free(ptr); ptr = NULL;
-
Be careful with pointer arithmetic
// Ensure you don't go out of array bounds if (ptr + i < arr + size) { // Safe to access }
-
Use const for pointers that shouldn't modify data
void printString(const char *str) { // str cannot be used to modify the string }
-
Match every malloc with free
int *ptr = (int*)malloc(100 * sizeof(int)); // Use ptr... free(ptr);
No comments to display
No comments to display