Common Memory/Pointer Related bug in C Programs - GeeksforGeeks

01 Oct, 2018
Dereferencing an unknown memory location : C programmers mostly use scanf() function to take input, but sometimes a small mistake can bring a bug or even crash whole program.The syntax for scanf() is scanf(“%d”, &a);. It might be possible to miss a & and write &a as a so now scanf(“%d”, a); is dereferencing to an unknown location.Now either the program may terminate with an exception or it may correspond to a valid location(not related to current program but to some other program) and may get overwritten which may cause unknown effect later.
// A C program to demonstrate that missing// an & in scanf() may cause memory problems.#include <stdio.h>  int main(){    int a;    scanf("%d", a);    printf("%d", a);    return 0;}
Reading an uninitialized Memory. In C, beginners generally use malloc() to provide run time memory but with malloc() the memory block do not get initialized and one may access .
// A C program to demonstrate that missing// an & may cause memory problems.#include <stdio.h>  int main(){    int* p = (int*)malloc(sizeof(int) * 4);    int i;      // p[] contains some garbage value so    // below loop does not make any sense.    for (i = 0; i < 4; i++)        p[i] += 100;}
A solution is to use calloc() instead which initialize block to 0.
Buffer overflow : This is a very common mistake that occur in C and this become even more common due to presence of a faulty function in C itself i.e. gets() function which is used to take string as input. It does not check the memory provided to store string in the program due to which if a user enter string of greater size then gets() with overwrite memory location after the string and cause overflow.
void read(){    char str[20];    gets(str);    printf("%s", str);    return;}
The code suffers from Buffer Overflow as gets() doesn’t do any array bound testing. gets() keeps on reading until it sees a newline character. To avoid Buffer Overflow, fgets() should be used instead of gets() as fgets() makes sure that not more than MAX_LIMIT characters are read.
#define MAX_LIMIT 20void read(){    char str[MAX_LIMIT];    fgets(str, MAX_LIMIT, stdin);    printf("%s", str);    return;}
Memory leaks This situation arises when the used heap memory is not de-allocated due to which the main memory get eventually filled up and free memory become less.
/* Function with memory leak */#include <stdlib.h>  void f(){    int* ptr = (int*)malloc(sizeof(int));      /* Do some work */      return; /* Return without freeing ptr*/}
We should use free() after malloc() if memory is not used anymore.
/* Function without memory leak */#include <stdlib.h>  void f(){    int* ptr = (int*)malloc(sizeof(int));      /* Do some work */      free(ptr); // Deallocate memory    return;}
Bug due to precedence Less understanding of operator and their precedence can produce a bug especially with pointers like
// C program to demonstrate bug introduced due// to precedence.#include <stdlib.h>  int demo(){    int a = 10;    int* p = &a;      // intention was to increase the value of a    *p++;}
Precedence of * (dereference/indirection operator not multiplication) and postfix ++ are not same but prefix ++ and * has same, and hence, first the value of p will increase and will point to a bad memory area and then dereference and will overwrite that location or program may get terminated. Please see Difference between ++*p, *p++ and *++p for details.
Sending address of non-existing variable Returning address of a local variable causes problems,
#include <stdlib.h>  int fun(){    int x = 10;    return &x;}int main(){    int* p = fun();    *p = 20;}
When function fun() is called variable a is created but as soon function returns, it get destroyed. Since function is returned its address p will point to a memory area in stack area and if another function is called then a change by pointer p may result in error.
Pointer arithmetic Pointer arithmetic can be confusing let’s take an example suppose integer is of 4 Bytes.
int main(){    int x[10] = { 0 }, i = 0, *p;      // p point to starting address of array x    p = &x[0];    while (i < 10) {        *p = 10;          // intention was to point to integer at x[1]        p = p + 4;        i++;    }}
Although it seems correct as integer is of 4 byte and p is at starting location so adding 4 to it will cause p to point at next integer in array n but pointer arithmetic work according to size of its data type so adding 1 to a pointer of integer then sizeof(int) will get added to it same applies for pointer to any other data type.
int main(){    int x[10] = { 0 }, i = 0, *p;    p = &x[0]; // p point to starting address of array x    while (i < 10) {        *p = 10;        p++; // means p = p + sizeof(int)        i++;    }}
Passing array as parameter When we pass an array to a function, it is always treated as a pointer in the function. That’s why we should never use sizeof on array parameter. We should rather always pass size as a second parameter.
#include <stdio.h>  // arr is a pointer even if we have// use square brackets.void printArray(int arr[]){    int i;      /* sizeof should not be used here to get number     of elements in array*/    int arr_size = sizeof(arr) / sizeof(arr[0]);     for (i = 0; i < arr_size; i++) {        printf("%d ", arr[i]);    }}  int main(){    int arr[4] = { 1, 2, 3, 4 };    printArray(arr);    return 0;}
Below is the corrected code
#include <stdio.h>  // arr is a pointer even if we have// use square brackets.void printArray(int arr[], int arr_size){    int i;    for (i = 0; i < arr_size; i++) {        printf("%d ", arr[i]);    }}  int main(){    int arr[] = { 1, 2, 3, 4 };    int arr_size = sizeof(arr) / sizeof(arr[0]);     printArray(arr, arr_size);    return 0;}
Reference :Computer Systems :A programmer’s Perspective
xdsarkar
C-Dynamic Memory Allocation
cpp-pointer
C Language
C++
CPP
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
TCP Server-Client implementation in C
Exception Handling in C++
Multithreading in C
'this' pointer in C++
Arrow operator -> in C/C++ with Examples
Vector in C++ STL
Initialize a vector in C++ (6 different ways)
Inheritance in C++
Map in C++ Standard Template Library (STL)
C++ Classes and Objects