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.
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 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.
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.
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.
We should use free() after malloc() if memory is not used anymore.
Bug due to precedence Less understanding of operator and their precedence can produce a bug especially with pointers like
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,
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.
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.
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.
Below is the corrected code
Computer Systems :A programmer’s Perspective