跳转至

Lecture 4: Memory (Mis)Management

Memory and Address

  1. Modern machine are byte-addressable.
  2. Word Size
    • A 32b architecture has 4-byte words.
    • All pointer sizes on 32b architecture: sizeof(int *) = ... = sizeof(char *) = 4

alt text

Endianness

  1. The hive machines are "little endian".
  2. "little endian": The least significant byte of a value is stored first.

alt text

Word Alignment

We wanna "word alignment" to avoid memory fragments

  1. Some processors will not allow you to address 32b values without being on 4-byte boundaries.
  2. Others will just be very slow if you try to access "unaligned" memory.

alt text

alt text

Sizeof()

alt text

there remains an issue

???

Memory Layout

alt text

alt text

Through this, we can easily understand 2 things:

  1. We can not change a value of a NULL pointer.
    • for it points to 0x00000000, which is in Text and cannot be written
  2. A variable can not exist once a function ends.
    • for it is in Stack and will be cleaned once a function ends.

Stack

alt text

alt text

Stack and Pointers

alt text

Heap

The heap is dynamic memory – memory that can be allocated, resized, and freed during program runtime.

  • Useful for persistent memory across function calls.
  • But biggest source of pointer bugs, memory leaks, …
  • Similar to Java new command allocates memory… but with key differences below.

Huge pool of mem (usually >> stack), but not allocated in contiguous order.

alt text

  • malloc(): Allocates raw, uninitialized memory from heap
  • free(): Frees memory on heap
  • realloc(): Resizes previously allocated heap blocks to new size
  • Unlike the stack, memory gets reused only when programmer explicitly cleans up

malloc

Format

C
1
void *malloc(size_t n) // notice: size_t == unsigned int

Allocates a block of uninitialized memory:

  1. size_t n is an unsigned integer type big enough to “count” memory bytes.
  2. Returns void * pointer to block of memory on heap.
  3. A return of NULL indicates no more memory (always check for it!!!)

Usage

Define a struct

C
1
2
3
4
5
6
7
8
9
typedef struct {...} TreeNode;
TreeNode* tp = (TreeNode *) malloc(sizeof(TreeNode));

/*
- (TreeNode *)
    - Typecast casts return value from type (void *) to (TreeNode *)
- sizeof(type)
    - gives size in bytes
 */

Allocate an array (of 20 ints)

C
1
2
3
4
5
6
7
8
9
int* ptr = (int *) malloc(20 * sizeof(int));
/*
    notice: sizeof is in "bytes", so 20 ints need 20*sizeof(int) space
*/

if (ptr !=  NULL){
    // always check NULL after
    ......
}

alt text

free

  • Dynamically frees heap memory
    • ptr is a pointer containing an address originally returned by malloc() / realloc().
C
1
2
3
int *ptr = (int *) malloc (sizeof(int) * 20); 
...
free(ptr); // implicit typecast to (void *)

When you free memory, be sure to pass the original address returned from malloc(). Otherwise, crash (or worse!)

realloc

Format

C
1
void *realloc(void *ptr, size_t size)
  • Resize a previously allocated block at ptr to a new size.
    • Returns new address of the memory block.
    • In doing so, it may need to copy all data to a new location.
  • realloc(NULL, size); // behaves like malloc
  • realloc(ptr, 0); // behaves like free, deallocates heap block

Usage

Remember: Always check for return NULL, which would mean you’ve run out of memory!

C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
int *ip; 
ip = (int *) malloc(10 * sizeof(int)); 

   /* check for NULL */

ip = (int *) realloc(ip, 20 * sizeof(int)); /* contents of first 10 elements retained */ 

   /* check for NULL */ 

realloc(ip,0); /* equivalent to free(ip); */
realloc may destroy the original data allocated by malloc

realloc函数尝试调整之前分配的内存块的大小。它可能会有以下几种结果:

  • 如果有足够的空间,它会直接扩展当前内存块,不移动数据。
  • 如果没有足够的连续空间,它会分配一个新的更大的内存块,将原数据复制过去, 然后释放旧块
  • 如果请求的新大小更小,它会收缩当前块 (基本用不到,不关心)。

working with memory

alt text

alt text

alt text

alt text

alt text