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