Pointer is the most important and powerful tool in C language. Pointer resolves many complicated problems easily but if you don’t have the sufficient knowledge of pointers, you will face problems like segmentation fault etc.
In this article, I will describe five common pointer mistakes in C programming which generally occurs.
What is pointer?
A pointer is a variable that stores memory address. If it is a variable, it must have a valid C data type. Yes, every pointer variable has a data type associated with it. Which means an integer pointer can hold only integer variable addresses.
There are numerous advantages of pointers, such as.
- Pointers are more efficient in handling arrays and structures.
- We use to return multiple values from a function.
- We use pointers to get reference of a variable or function.
- Pointer allows dynamic memory allocation (creation of variables at runtime) in C.
- Pointers increases execution speed of program.
Common pointer mistakes and how to avoid them
Despite of its advantages, if not used correctly pointers can be severely dangerous to your program. Let us cover some common pointer mistakes in C programming. And learn how to avoid common pointer mistakes.
Uninitialized Pointer
Like all variables initialization, we should always initialize a pointer variable. Behaviour of uninitialized pointers is undefined, hence we should always initialize a pointer prior to use. In C programming terminology an uninitialized pointer is termed as Wild pointer.
Example:
int *crazyPointer; // wild pointer
It is always a good idea to initialize a pointer with NULL
(null pointer) at the time of its declaration.
int *calmPointer = NULL;
Access a freed pointer
We use free()
function in C programming to release memory allocated by a pointer.
Read more about Dynamic memory allocation and deallocation in C.
After calling free()
function, pointer still point at the same allocated memory address. So, you might succeed but it is illegal and behavior of accessing freed pointer (memory location) is undefined. The freed pointer is also called the dangling pointer.
Example:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *ptr = NULL;
// Creating integer of size 5
ptr = malloc(sizeof(int) * 5);
// Unable to allocate memory
if (ptr == NULL)
return 0;
// Free the allocated memory
free(ptr);
// ptr is dangling pointer
// Behaviour of this is undefined
*ptr = 50;
return 0;
}
Note: It is always good habit to assigned NULL
(null pointer) to a freed pointer.
Read more about void pointer in C language.
Forget to check the return value of memory management function
Dynamic memory allocation functions, returns pointer to the allocated memory on success otherwise NULL
(null pointer). Generally, people forget to check the return value of memory management functions (malloc()
, calloc()
,.. etc).
Read more about How to pass and return multiple value from a function?
These functions return a valid allocated memory on success, on failure they return NULL
. So, we should always check the return value of these function. This help you to prevent from segmentation fault.
Example: Bad way to use dynamic memory allocation
// Allocate memory to accommodate an integer
int *ptr = malloc(sizeof(int));
// Assign value to the newly allocated memory
// This assignment may cause segmentation fault
// Since we are assigning value to a dynamically
// allocated memory, without check whether it got
// allocated successfully or not.
*ptr = 10;
Good way to use dynamic memory allocation
int *ptr = malloc(sizeof(int));
// Terminate, if memory not allocated successfully
if(ptr == NULL)
return 0;
// Assign value to newly allocated memory after
// checking memory allocation
*ptr = 10;
Forget to free dynamically allocated memory
When managing memory manually, you must take care of proper memory allocation and deallocation. You should always free the allocated memory.
If you forget to deallocate the allocated memory, then the allocated memory is not available to another process and it is reserved for the entire life of the program. It is the one of the important cause of the memory leaks.
Example:
#include <stdio.h>
#include <stdlib.h>
int main ()
{
// Allocate 20 bytes memory
char * ptr = malloc(sizeof(char) * 20);
/* Do some work */
// Not freeing the allocated memory
return 0;
}
To avoid memory leaks, you must deallocate the dynamically allocated memory.
Example: Avoid memory leaks in above program
#include <stdio.h>
#include <stdlib.h>
int main ()
{
// Allocate 20 bytes memory
char * ptr = malloc(sizeof(char) * 20);
/* Do some work */
// Free the allocated memory afters its use
free(ptr);
return 0;
}
Freeing the same memory multiple times
We use free()
function to deallocate dynamically allocated memory. The behaviour of free()
function is undefined, if you try to free memory that is already deallocated (using free()
or realloc()
).
Freeing memory twice is more dangerous then memory leaks. So, it is good habit to assign NULL
to the deallocated pointer because free()
function does not perform anything with null pointer.
Example:
#include <stdio.h>
#include <stdlib.h>
int main()
{
// Its always good to initialize pointer with NULL
int *ptr = NULL;
// Allocate integer of size 10.
ptr = malloc(sizeof(int) * 10);
// Check if memory allocated successfully
// if (ptr != NULL) is equivalent to if (!ptr)
if (!ptr)
{
printf("Unable to allocate memory");
return;
}
// free dynamically allocated memory
free(ptr);
// Assign NULL to deallocated memory
ptr = NULL;
// Free dynamically allocated memory twice
free(ptr);
return 0;
}
Happy coding 😉