Programming in C: Unit III (b): Pointers

Drawbacks of Pointers

Programming in C

Although pointers are very useful in c they are not free from limitations. If used incorrectly, pointers can lead to bugs that are difficult to unearth.

DRAWBACKS OF POINTERS

Although pointers are very useful in c they are not free from limitations. If used incorrectly, pointers can lead to bugs that are difficult to unearth. For example, if you use a pointer to read a memory location but that pointer is pointing to an incorrect location then you may end up reading a wrong value. An erroneous input always leads to an erroneous output, therefore however efficient your program code may be, the output will always be disastrous. Same is the case when writing a value to a particular memory location.

Consider a scenario in which the program code is supposed to read the account balance of a customer, add new amount to it, and then re-write the modified value to that location. If the pointer is pointing to the account balance of some other customer then the account balance of the wrong customer will be updated.

Let us try to find some common errors encountered when using pointers.

int x, *px;

x = 10;

*px = 20;

Error un-initialized pointer. px is pointing to an unknown memory location. Hence it will overwrite that location's contents and store 20 in it. Such pointer is called a wild pointer. A pointer which is not initialized with any address is called a wild pointer. It may contain any garbage address and thus dereferencing a wild pointer can be dangerous.

int x, *px;

x = 10;

px = x;

ERROR: it should be px = &x;

int x = 10, y = 20, *px, *py;

px = &x, py = &py ;

if (px < py) // it should be *px and *py

printf("\n px is less than py");

else

printf("\n py is less than px");

Look at another code given below.

#include <stdio.h>

main()

{

char *strl, *str2;

printf("\n Enter the string: ");

gets (str1);

while (*str1!= '\0')

{

*str2 = *str1;

str2++, str1++;

}

*str2='\0';

printf("\n String is: ");

while (*str2 != '\0')

{

printf("%c", *str2);

str2++;

}

}

Error str2 will not be printed because str2 has moved ahead of its starting location and before displaying the string, it has not been initialized with its starting address.

Memory leak Memory leakage occurs when memory is allocated but not released when it is no longer required. This causes an application to unnecessarily consume memory thereby reducing the memory available for other applications. Although in small programs it is not a big concern but when dealing with large projects, memory leakage may result in slowing down the application or crashing the application when the computer memory resource limits are reached.

For example, if a function dynamically allocates memory for 100 double values and forgets to free the memory and in worst case if that function is called several times within the code then ultimately the system may crash.

Dangling pointer Dangling pointers arise when an object is deleted or de-allocated, without modifying the value of the pointer. As a result, the pointer still points to the memory location of the de-allocated memory.

Once the memory is de-allocated, the system may reallocate that block of freed memory to another process. In case the program then dereferences the (now) dangling pointer, unpredictable behaviour may result, as the memory may now contain completely different data.

This problem can become worse when the program writes data to memory pointed by a dangling pointer causing a silent corruption of unrelated data, leading to subtle bugs that can be extremely difficult to find. Moreover, if the overwritten data is bookkeeping data used by the system's memory allocator, the corruption can even cause system instabilities.

Hence, dangling pointer problem occurs when the pointer still points to the same location in memory even though the reference has been deleted and may now be used for other purposes.

A common mistake that we often do in C program is to return address of a stack-allocated local variable. We know that once a called function returns, the space for these variables gets de-allocated and technically they have garbage values. Look at the code below which illustrates how we get a dangling pointer when a called function returns.

char *func (void)

{

Char ch='A';

/* ... */

return & ch;

}

The above program returns the address of ch. So the calling function may access its value. Any functions called thereafter will overwrite the stack storage allocated for ch with other values and the pointer would no longer work correctly. Therefore, if a pointer to ch must be returned it must be declared as static.

Consider the code below which illustrates another dangling pointer problem.

char *ptr1;

char *ptr2 = (char *)malloc(sizeof(char));

ptr1 = ptr2;

free (ptr2);

Now ptr1 becomes a dangling pointer. A solution to the above is to assign 0 (null) to ptr1 immediately before exiting the block in which it is declared. An alternative solution would be to somehow guarantee that ptr1 will not be used again without further initialization.

Memory corruption Memory corruption often occurs when due to programming errors, the contents of a memory location gets modified unintentionally. When the program uses the contents of the corrupted memory, it either results in program crash or in strange and bizarre behaviour.

Memory corruption is one of the most difficult pro- gramming errors to trace mainly because of two reasons:

• The source of the memory corruption and its manifestation may be far apart. Therefore, it may become hard to correlate the cause and the effect of the problem.

• Symptoms of memory corruption problem may appear under unusual conditions thereby making it even harder to consistently reproduce the error.

Memory corruption errors can be broadly classified into following categories:

1. Using un-initialized memory: An un-initialized ai m memory contains garbage value. Hence, using the contents of an un-initialized memory can lead to unpredictable program behaviour.

2. Using un-owned memory: A common programming mistake is to use pointers for accessing and modifying memory that is not owned by the program. This situation may arise when the pointer happens to be a null pointer or a dangling pointer. Using such a pointer to write to a memory location is a serious programming flaw as it may lead to crash another program or even the operating system.

3. Using beyond allocated memory (buffer overflow): If the elements of the array are accessed in a loop, with incorrect terminating condition, memory beyond the array bounds may be manipulated. Buffer overflow is a common programming flaw exploited by computer viruses causing serious threat to computer security.

4. Faulty de-allocation of memory: Memory leaks and freeing un-allocated memory can also result in memory corruption.

These days, memory debuggers like Purify, Valgrind, Insure++ are widely used for detecting memory corruption errors.

Programming in C: Unit III (b): Pointers : Tag: : Programming in C - Drawbacks of Pointers