Pointers

Variable Declarations

•      Declarations served dual purpose

–   Specification of range of values and operations

–   Specification of Storage requirement

 

•      All programs required FIXED amount of memory

–   number of variables fixed by the declaration

–   decided by their types

 

•      One exception:  Allocatable array

–   Size of the array depends upon input

Static and Dynamic Allocation

•      Compiler uses the declaration to allocate memory for a program

•      Static allocation (or fixed  memory requirements) leads you to be conservative

•      Wastage of space and poor performance for some inputs

•      Analogy:  Two-way traffic in City roads

•      Better management: allocate on demand

–    Initially allocate minimal

–    Allocate more when needed

–    Deallocate when not needed

–    Dynamic Memory management

Dynamic Memory allocation

•      Memory allocation not fixed

•      nor done at compile-time

•      It is done at run-time

•      at run-time no declarations - only executable instructions

•      need special instructions for allocation - executable declarations so to say

•      Allocate and Deallocate constructs for dynamic arrays

•      we need more general mechanism for arbitrary organization of data

Pointers

•      One problem with dynamic allocation:

•      How do we access the newly allocated memory locations

•      How did we access the statically allocated memory?

•      Access the new locations by their addresses

•      This is against the principle of high level languages:

–   abstract memory locations and machine details

–   disallow direct control over resources – unsafe

•      is there any other way?

•      pointer variables is a compromise

•      Pointer variable contains addresses rather than data values

•      Addresses point to the newly allocated memory locations and hence called pointers

Pointer variables

•      They store addresses that identify locations where actual data values reside

•      Pointer variables declared statically so compiler can allocate memory

•      Static declaration of pointer variables! That is funny

–    we do not know a priori our memory requirement and hence our quest for dynamic memory locations

•      Static declarations can allocate only a fixed number of pointers

•      How do we create and access unbounded number of locations

•      Answer: Dynamic creation of pointers themselves (more on this later)

Pointer variable Declarations

•      Declarations specify types - set of data values and operations

•      What types pointers are or should be?

•      Pointer variables store addresses

•      Addresses are numerical values - non negative integers

•      Are they non negative integers? No, quite a different kind

•      Pointers always contain same type of values whatever they point to

–   Can point to integers, reals, characters, arrays or structures

•      Are all pointers of the same type

Pointers are of different types

•      Only way of accessing dynamic objects is through pointers

•      What is pointed to is distinguished - real, integer, character, array etc.

•      Essential to distinguish the pointers for the same reason

•      So Pointers are of different types:

–   integer pointer, real pointer, array pointer, etc

•      Pointer types are decided by the types of those pointed to

•      Declarations specify these

Pointer Declarations

•      Examples:

            integer, pointer:: p1, p2

            real, pointer:: r1, r2

 

            integer, dimension(:), pointer:: array_ptr

            real, dimension(:,:), pointer:: matrix_ptr

•      These declarations allocate memory for the pointer variables

•      Pointer variables have addresses like normal addresses

•      But they store addresses - the addresses will be assigned dynamically (during execution)

•      Addresses assigned should correspond to locations where data values with the specified type is stored

•      Special statements are provided for this purpose

Target variables

•      Simplest pointer assignment:

–   store the address of a location allocated for a variable

•      Example:

          p1 => x

          r1 => z

          matrix_ptr => m

    where

–      p1,r1, matrix_ptr as before

–      x,z,m are integer, real and matrix variables

•      The types should match

•      rhs variables resolved to addresses!

–   contrast with conventional assignment

Pointer assignment

 

 

Target declarations

•      For a variable to act as target explicit declaration required:

 

          integer, target :: x

          real, target :: z

          integer, dimension(10,10), target :: matrix_ptr

Targets can be pointers

•      Suppose p1 and p2 are of pointers of the same type

 

•      Further suppose p2 points to a location of appropriate type

 

•      Then

            p1 => p2

 

•      makes p1 point to whatever p2 points to

 

Before Assignment

 

 

 

After assignment

 

 

 

Dereferencing of pointers

•      Two meanings for pointers in

          p1 => p2

•      p2 has an address and contains another address

•      What is assigned to p1 is the content of p2

•      p2 on the rhs refers to the contents of p2 rather than p2 itself

•      This is called Dereferencing

•      Contrast this when target is ordinary variable

          p1 => x

–   what is assigned here is not the content of x but the address of x

Another example

•      Consider

  

write *, p1, p2

 

•      What is printed?

•      The address associated with p1,p2?

•      No, the values stored at those addresses

•      The pointers are dereferenced to get the values

Pointers in Normal Assignment

•      Pointers can appear in normal assignments:

•         p1 = p2

•         p1 = p2 + p3

 

•      Suppose, p1, p2 and p3 points to targets x, y and z

•      The above is equivalent to

•          x = y

•          x = y + z

 

•      Note that p1 is also dereferenced here

Rules for dereferencing

=>

•      The lhs should be evaluated to an address (or pointer)

•      The rhs should also evaluate to an address

=

•      The lhs should evaluate to an address

•      The rhs should evaluate to a value

print *, x

–   x should be a value

•      So the rule is:

             Dereference the pointer as much required to         evaluate to appropriate value

Use of Pointers

•       Suppose you wish to exchange two arrays arr1, arr2 of Dimension(100,100)

•       Solution 1:

            temp = arr1

            arr1 = arr2

            arr2 = temp

•       involves exchange of 10,000 values!

•       Solution 2:

            Real, Dimension(:,:), pointer:: p1,p2,temp

            p1 => arr1

            p2 => arr2

            temp => p1

            p1 => p2

            p2 => temp

•       Exchange of just two pointers

Dynamic Allocation of Memory

•      So far, pointers point to already existing variables

•      The amount of used memory is still static

•      For dynamic memory requirement, additional mechanism needed

•      Allocate and Deallocate instructions

•      Allocate ‘creates’ required memory and decllocate ‘destroys’ memory

Allocate Command

•      Simplest allocate statement

                Allocate(p, stat = s)

•      This allocates appropriate memory space,

•      address pointed to by the pointer p

•      s returns an integer value which indicates whether allocation successful or not

          s = 0 means success,

                    failure otherwise

•      Stat = is optional but should always be used

•      If allocation fails and if no stat = clause, then the program will abort

Some examples

             integer, pointer:: p1

          integer, dimension(:):: p2

          ...

          allocate(p1, Stat=p1_stat)

          allocate(p2(1:10), Stat = p2_stat)

          '''"

 

          p1 = x + y

          p2(2) = p2(1) + p1

 

•      Note the dimension specification in p2 declaration

Deallocate Command

•      Memory created using Allocate command can be destroyed when not needed

–   Deallocate(p, Stat = p_stat)

•      Deallocates the memory, if p_stat = 0

•      What does p point to after this command?

•      It points to null value

•      Pointer assignment or allocation associates the pointer with some address

•      Deallocation breaks this association

•      Referring to pointer that is disassociated is an error

–   The program will abort

Checking Association

•      To avoid aborting, association status of pointer should be checkable

•      Intrinsic function Associated  used for this purpose

associated(p)

•      returns the value .TRUE. iff p is associated with a target

•      A more general form is

                associated(p, tvar)

•      returns .TRUE iff p is associated with the target tvar

•      Association with a pointer can be removed using

                nullify(p)

•      which disassociates p with any target.

Pointers - serious safety hazard

•      Conventional variables have many nice features:

–   unique association of memory with variables

–   distinct variables - distinct locations

–   one without the other not possible

•      Pointers provides flexibility and more control

•      But at the cost of safety

•      It is a low-level feature

•      No unique association of pointers to targets

•      More than one pointer to the same target or location

•      Pointer without location (dangling pointers)!

•      Location without any pointers too (memory leak or garbage)!

Multiple Associations

            p1 => x

            p2 => p1

            p3 => p2

            p4 => x

•      All point to the same location

 

 

Dangling Pointers

•      What is the problem with multiple associations?

•      value pointed to by p1 can be changed independently

            p1 = 10

            p2 = 17

            p1 = p1 + 1

     p1 points to a location which contains 18 and not 11

•      More serious problem:

            p1 = 10

             deallocate(p2)

            p1 = p1 + 2

•      p1 is pointing to a location which is deallocated

•      p1 is a dangling pointer

•      no control over what value the deallocated memory will contain

Memory Leak

•      Only way of accessing dynamically allocated memory is via pointers

•      Suppose there is only one pointer p pointing a location

•      nullify(p) disassociates p

•      The memory is no longer accessible

•      Memory has leaked out - memory has become garbage

•      Deallocation done before memory leaks out

•      Wastage of space

•      Separate Garbage collection phase