Wild pointer
|
Wild pointers are pointers that have not been initialized (set to point to a valid address) and can make a program crash and/or behave oddly. This is due to the fact that in the programming language C, pointers that were not specifically initialized point to unpredictable addresses in memory.
Examples
The following example code shows a wild pointer:
#include <stdio.h> #include <memory.h> int main(void) { char *p1 = (char *)malloc(sizeof(char *));// initialized pointer printf("Address of p1: 0x%x\n", p1); // points to some place in the heap printf("Value of *p1: 0x%x\n", *p1); // (undefined) value of some place in the heap char *p2; // wild (uninitialized) pointer printf("Address of p2: 0x%x\n", p2); // undefined value, may not be a valid address // if you are LUCKY, this will cause an addressing exception printf("Value of *p2: 0x%x\n", *p2); // random value of random address //the program probably already crashed before it reaches return return 0; }
The problems with invalid pointers include more than simply uninitialized values.
For instance, pointers can still exist after the variables that they point to no longer exist. This can happen if the pointer still exists after the variable it points to has gone out of scope, as in the example below. If such an invalid pointer is used, the program will probably not immediately crash, but the result will still probably be incorrect, and the failure will probably be hard to track down.
#include <stdio.h> #include <memory.h> int badIdea(int **p) // p is a pointer to a pointer to an int { int x = 1; // allocate an int on the stack **p = x; // assign value of x to int that pointer p points to *p = &x; // make the pointer that p points to point to x return x; // after return x is out of scope and undefined } int main(void) { int y = 0; int *p1 = &y; // initialized pointer to y int *p2 = NULL; // a good habit to form printf("Address of p1: 0x%x\n", p1); // prints address of y printf("Value of *p1: 0x%x\n", *p1); // prints value of y y = badIdea(&p1); // changes y and changes p1 // p1 now points to where x was // The place where x was will get clobbered, // for instance, on the next interrupt, or on // the next subroutine call, as below.... // some other code that also uses the stack p2 = (int *)malloc(5*sizeof(int)); // this probably will NOT crash, but value printed is unpredictable printf("Value of *p1: 0x%x\n", *p1); // prints value of where x was return 0; }
A very common problem is using a pointer to the heap after that memory has been deallocated, as in this example. The invalid copies of the pointer are usually much harder to find than here.
#include <stdio.h> #include <memory.h> int main(void) { int *p1 = (int *)malloc(sizeof(int)); // initialized pointer to heap int *p2 = p1; // make a copy *p1 = 0; // initialize the heap printf("Address of p2: 0x%x\n", p2); // points into the heap printf("Value of *p2: 0x%x\n", *p2); // should print zero free(p1); // deallocate the memory .... // other code, possibly using the heap // p2 still points to the original allocation, but who knows what is there printf("Value of *p2: 0x%x\n", *p2); // invalid use of p2 return 0; }
A third way that pointers can be misused is to access outside the data structure they point to. Here is a simple example.
#include <stdio.h> #include <memory.h> int main(void) { int y = 5; // create a variable int *p1 = &y; // initialized pointer to y printf("Address of p1: 0x%x\n", p1); // address of y printf("Value of *p1: 0x%x\n", *p1); // value of y p1 = p1 + y; // allowed pointer arithmetic printf("Value of *p1: 0x%x\n", *p1); // p1 no longer points to y return 0; }
If a pointer is used to write beyond the end of a local buffer, the stack can be destroyed. In the case below, the problem will probably manifest when the main program returns.
#include <stdio.h> #include <memory.h> // copy source to destination, no check on sizes void strcopy(char *d, char *s) { while (*d++ = *s++) // copy until '\0' encountered ; } int main(void) { char y[3]; // create a local buffer char *p1 = (char *)malloc(10*sizeof(char)); // another buffer on heap p1[9] = '\0'; // terminate the larger buffer strcopy( y, p1); // overflow the local buffer free(p1); return 0; // now bad stuff happens }