What is the Problems with Pointers
Problems with Pointers
Nothing will get you into more trouble than a wild pointer! Pointers are a mixed blessing. They give you tremendous power and are necessary for many programs. At the same time, when a pointer accidentally contains a wrong value, it can be the most difficult bug to find. An erroneous pointer is difficult to find because the pointer itself is not the problem. The problem is that each time you perform an operation using the bad pointer, you are reading or writing to some unknown piece of memory. If you read from it, the worst that can happen is that you get garbage. However, if you write to it, you might be writing over other pieces of your code or data. This may not show up until later in the execution of your program, and may lead you to look for the bug in the wrong place. There may be little or no evidence to suggest that the pointer is the original cause of the problem. This type of bug causes programmers to lose sleep time and time again. Because pointer errors are such nightmares, you should do your best never to generate one. To help you avoid them, a few of the more common errors are discussed here. The classic example of a pointer error is the uninitialized pointer. Consider this program.
/* This program is wrong. */
int main(void)
{
int x, *p;
x = 10;
*p = x;
return 0;
}
This program assigns the value 10 to some unknown memory location. Here is why: Since the pointer p has never been given a value, it contains an unknown value when the assignment *p=x takes place. This causes the value of x to be written to some unknown memory location. This type of problem often goes unnoticed when your program is small because the odds are in favor of p containing a “safe” address—one that is not in your code, data area, or operating system. However, as your program grows, the probability increases of p pointing to something vital. Eventually, your program stops working. The solution is to always make sure that a pointer is pointing at something valid before it is used.
A second common error is caused by a simple misunderstanding of how to use a pointer. Consider the following:
/* This program is wrong. */
#include
int main(void)
{
int x, *p;
x = 10;
p = x;
printf(”%d”, *p);
return 0;
}
The call to printf() does not print the value of x, which is 10, on the screen. It prints some unknown value because the assignment
p = x;
is wrong. That statement assigns the value 10 to the pointer p. However, p is supposed to contain an address, not a value. To correct the program, write
p = &x
Another error that sometimes occurs is caused by incorrect assumptions about the placement of variables in memory. You can never know where your data will be placed in memory, or if it will be placed there the same way again, or whether each compiler will treat it in the same way. For these reasons, making any comparisons between pointers that do not point to a common object may yield unexpected results. For example,
char s[80], y[80];
char *p1, *p2;
p1 = s;
p2 = y;
if(p1 < p2) . . .
is generally an invalid concept. (In very unusual situations, you might use something like this to determine the relative position of the variables. But this would be rare).
A related error results when you assume that two adjacent arrays may be indexed as one by simply incrementing a pointer across the array boundaries. For example,
int first[10], second[10];
int *p, t;
p = first;
for(t=0; t<20; ++t) *p++ = t;
This is not a good way to initialize the arrays first and second with the numbers 0 through 19. Even though it may work on some compilers under certain circumstances, it assumes that both arrays will be placed back to back in memory with first first. This may not always be the case. The next program illustrates a very dangerous type of bug. See if you can find it.
/* This program has a bug. */
#include
#include
int main(void)
{
char *p1;
char s[80];
p1 = s;
do {
gets(s); /* read a string */
/* print the decimal equivalent of each
character */
while(*p1) printf(” %d”, *p1++);
} while(strcmp(s, “done”));
return 0;
}
This program uses p1 to print the ASCII values associated with the characters contained in s. The problem is that p1 is assigned the address of s only once. The first time through the loop, p1 points to the first character in s. However, the second time through, it continues where it left off because it is not reset to the start of s. This next character may be part of the second string, another variable, or a piece of the program! The proper way to write this program is:
/* This program is now correct. */
#include
#include
int main(void)
{
char *p1;
char s[80];
do {
p1 = s;
gets(s); /* read a string */
/* print the decimal equivalent of each
character */
while(*p1) printf(” %d”, *p1++);
} while(strcmp(s, “done”));
return 0;
}
Here, each time the loop iterates, p1 is set to the start of the string. In general, you should remember to reinitialize a pointer if it is to be reused.
The fact that handling pointers incorrectly can cause tricky bugs is no reason to avoid using them. Just be careful, and make sure that you know where each pointer is pointing before you use it.
Popularity: 1% [?]