One global shared i.
Each instance has its ‘own’ j.
Instance Variables:
Structs in C:
• Similar to objects in Java, fields are stored contiguously in memory. BUT: structs don’t have instance methods, just data fields
• Similar to arrays, structs can be allocated statically or dynamically. • To access an instance variable: need a reference to the struct,
then add the offset to the specific instance variable.
Allocation and Access
. notation: offset from the base address
-> notation: follow pointer, and then add offset to the base address
Breakout Question. Given the declaration.
Write out the assembly code for i = s->hope;
Declaration and Alignment
struct { int emo; int ji;
int hope;
} *s; int i;
ld $i, r0
ld $s, r1
ld (r1), r1 ld 8(r1), r2 st r2, (r0)
Calculate the sizeof and offsets to j? Assume a 32-bit machine
Static:
Struct D d0;
void foo1() {
d0.e = 4;
} d0.f = 6;
Address 0x1000 0x1004
…
Value
What is the difference between the following structs?
The first option is similar to the implementation of linked list, the sizeof(Z) is 12bytes. The second one is problematic, we would run out of memory training to implement it, because defining the struct within the struct, means we never know the size of Z
Draw out a memory representation:
Why?
Memory alignment. Variables aligned according to size. Second example (struct Y) : Because of arrays. If size was 9, second array element position would be unaligned
0 4 0 6
d0d0.e d0.f
Dynamic:
Struct D* d1
void foo2() { Additional mem access d1 = malloc(sizeof(struct D)); d1->e = 3;
} d1->f = 2;
Memory Addressing Modes
Assign a[3] = 5; using base+offset
ld $a, r0
ld $3, r1
ld $5, r2
st r2, (r0, r1, 4)
ld $a, r0
ld $5, r1
st r1, 12(r0)
Assign d0.f = 7; using indexed
ld $d0, r0
ld $7, r1
st r1, 4(r0)
ld $d0, r0
ld $1, r1
ld $7, r2
st r2, (r0, r1, 4)
Memory Deallocation
In C, malloc(n) allocates n bytes of memory and returns the address.
int *x = malloc(n);
Free releases the memory immediately. For example, free(x):
• de-allocates the memory block beginning at address x • memory block can later be allocated (by later malloc) • does NOT change the value at address pointed to by x
Common Memory Allocation and Access Bugs
Memory leak: failure to free allocated mem that’s no longer needed Dangling pointer: a pointer to a memory location that has been freed
What issue does each code block have?
Memory leak
Dangling pointer
Code is correct
Dangling pointer to stack mem. addr
Code is correct
At the point that we free p, p is not pointing to its original location (p could even be pointing to the same space as g!). So the original block for p was never deallocated (memory leak), and free is called on an invalid address (dangling pointer).
Why even use pointers?
Consider the alternative to passing a pointer to an array or a struct: Pros: passing a pointer is a lot cheaper than copying over all of the contents of an array or a large struct (speed + memory usage)
Cons: memory management. We need to remember to de-allocate objects when we no longer need them, and also make sure we aren’t accessing memory that is no longer valid.
Tips for Reference Counting
• Identify all the places where mem is being allocated: change from malloc to rc_malloc
• Identify all the places where mem. Is being deallocated: change from free to rc_free_ref
• Identify all the places where refs. are being made and decide what to do o If fn returns a ref – the ref count stays the same, do nothing unless o If fn gets a ref and doesn’t keep it – free_ref
o If fn consumes a ref and stores it – keep_ref
o If pointer is not null, make sure you do a free_ref before you change it and keep the new ref to ensure no mem. leaks
• Adding free_ref may have introduced dangling pointers, identify all the places where there are dangling pointers (i.e. accessing data members after free) – use local variables to address this issue or set pointers to null (if applicable)
• NOTE: In general, the tips above work, but at every point of your code, ask yourself, how many refs should there be to this mem block and use that to decide what to do regarding the ref count.
• DRAW IMAGES ooooooooothey are very helpful.
Three ways of managing dynamic memory allocation
1. Manual ref counting – our way using refcount 2. Automatic ref counting – python, swift
3. Garbage collection – Java
Memory Management Summary
What are the advantages of C’s explicit delete (free)?
More control for the programmer, less overhead.
What are the advantages of reference counting?
Monitor # pointers to dynamic object – we know when to free.
What are the advantages of Java’s garbage collection?
Above is a lot of work, easy to make a mistake – let Java handle it. No dangling pointers, reference cycles is not a problem
Is it okay to ignore deallocation in Java programs?
No, you can still end up with memory leaks