Notes : C++ – Part 3

< Previous (C++ – Part 2) | (C++ – Part 4) Next >

NOTIFICATION: These notes are published for educational purposes. Using these notes is under your own responsibility and risk. These notes are given ‘as is’. I do not take responsibilities for how you use them.

PDF Content:

  • Const correctness (continued)
  • Const member function
  • Pointers
  • Pointers and Arrays
  • Array of pointers
  • Pointers vs. Arrays
  • Allocating a memory
  • Data type class pointer
  • Passing to function by reference using pointers
  • Memory leaks
  • Pointers with increase and decrease operators
  • Pointers to pointers
  • Void pointers
  • Null pointer
  • Pointers to functions
  • Pointers to members
  • Pointer to member operators .* and ->*
  • Casting pointers to members
  • Difference between .* and ->* operator
  • Convert a pointer-to-member-function to void
  • Maps

Cplusplus_3

 

< Previous (C++ – Part 2) | (C++ – Part 4) Next >

 

 

Share

Dangling and Wild Pointers in C/C++

When we define a variable, memory is allocated for that variable.

/* definition of a variable with a size memory allocated of one byte */
char character;

This declare that the name character is of type char.

As you may know, we use pointers in order to manipulate data in the memory. Pointers are designed to store a value which is a memory address. However, if a defined pointers is not instantiated then this pointer may have a memory address pointing to any place in memory. This is pointer is called a “dangling pointer”. For example,

/* Dangling pointer */
char* c_pointer;

char character;
char* c_char_pointer = &character;  /* No dangling pointer */

Lets assume we defined a dangling pointer and we attempt to print the content of the memory address that may store in the dangling pointer:

int* dangling_pointer;
printf('%d', *dangling_pointer);

This would give us segmentation fault.

Lets assume we define a pointer, integer_pointer,  and we make sure that this pointer is not dangling by instantiated with NULL. Later in the our program, we define a variable inside brackets, integer_variable, and we assign the address of this variable to our pointer. The moment we get out of the brackets, the variable integer_variable will be out of scope (This means that this variable disappear in our program).

int main(int argc, char* argv[]){

  int* integer_pointer = NULL;
  ... /* Dots means that there are more code not included in the example */

  { /* integer_variable exist only between this brackets */
    int integer_variable = 100;
    integer_pointer = &integer_variable;
    ...
  } /* After this bracket, integer_variable is out of scope */
  ...

  *integer_pointer = 150;
  ...

  return 0;
}

This could produce unpredictable behaviour because the address store in the integer_pointer could be pointing to a sector in memory used for another program or another part of the program.

When using dynamic memory allocation such as malloc or new, the moment that we free the pointer, it becomes dangling. Therefore, it is a good policy to point the pointer to NULL. Why? Because the memory that was obtained by malloc or new will not exist anymore since it was freed by free.

#include <malloc.h>
...
int main(int argc, char* argv[]){
  ...

  char* character_pointer = malloc(sizeof(char));
  ...

  /* character_pointer is freed and become a dangling pointer */
  free(character_pointer); 

  /* Point the pointer to NULL so it is not dangling anymore */
  character_pointer = NULL;
  ...

  return 0;
}

Sometimes is said that an dangling pointer is a wild pointer; however, there is a distinction. While a dangling pointer is a wild pointer, a wild pointer may not be a dangling pointer… What?!! (You may ask) Let me explain.

The different is the instantiation of the variable. Lets define to pointers:

char* character_pointer_1;
char* character_pointer_2;

Both pointers can be called dangling and/or wild pointers because they are not instantiated. Now lets assume we instantiate character_pointer_1.

char* character_pointer_1;
char* character_pointer_2;
...
character_pointer_1 = malloc(sizeof(char));
...
free(character_pointer_1);
...

In this case, things change because character_pointer_1 was instantiated and later freed (with free). character_pointer_1 is called dangling pointer for the fact that it was instantiated before, while character_pointer_2 is called wild because it was never instantiated.

Share

Function Pointers in C/C++

In the previous post, we cover how to work pointers with arrays. In this post we will see how to use function pointers, and how useful they can be:

I am assuming that you read the previous postings about pointers and pointers with arrays.

As we may recall, when we declare a pointer, the pointer will store an address of a position in memory.
Normally, we wish to create pointers of the same kind as the object we want to point at. For example, if the variable is an integer then we want the pointer to be an integer:

int i_variable = 22;
int* pi_variable = &i_variable;

If you create a different variable of the same kind, you could change where the pointer is pointing at:

int i_variable = 22;
int i_variable_2 = 44;
int* pi_variable = &i_variable;
printf('Value pointed at: %d \n', *pi_variable);     /* This line print 22 */
pi_variable = &i_variable_2;                         /* pi_variable points at i_variable_2 */
printf('New Value pointed at: %d \n', *pi_variable); /* This line prints 44 */

Now the question comes, can we use this with functions? Yes, we can!

Here is an example of how this works:

/* This return the addition of value_a with value_b */
int add(int value_a, int value_b){
	return value_a + value_b;
}

/* This function return the subtraction of value_b from value_a */
int sub(int value_a, int value_b){
  return value_a - value_b;
}

int main(int argc, char* argv[]){
  int val_a = 4;   
  int val_b = 5;

  /* Function pointer  must have the same return type and parameter type */
  int (*p_function)(int, int);

  p_function = add;
  printf('ADD A: %d with B:%d to obtain %d \n', 
         val_a, 
         val_b, 
         (*p_function)(val_a, val_b));

  p_function = sub; 
  printf('SUBTRACT B: %d OF A:%d to obtain %d \n', 
         val_b, 
         val_a, 
         (*p_function)(val_a, val_b));

return 0;
}

This will print:

ADD A: 4 with B:5 to obtain 9
SUBTRACT B: 5 OF A:4 to obtain -1

As you can see this can be a very powerful feature. The function pointer will point to the address of any function we want to point at while the function have the same return type (int in this case), the same number of parameters (in this case, we have two parameters), and the same type of parameters (both parameters are int).

Share