We want:

  • memory that sticks around when exiting functions
  • too big for stack
  • but need it dynamic
    • not .text as not read/write
    • cannot go into .data, .bss as size is not known pre-execution.
      → For this we need dynamically allocated memory via malloc (to allocate a memory region on the heap).

get’s freed on program end by OS, or deallocated manually / by GC.

Memory Management in C

typedef

typedef unsigned long size_t;
void *malloc(size_t sz);

returns a pointer to a block of memory at least as long as size bytes.

  • returns NULL if it didn’t work

DO NOT Assume that the memory is 0 → uninitialised

Note: Pages vs. Malloc’ed memory
Note that the program mmaps an entire page (which the OS hands zeroed). Malloc then internally manages those pages.

  • thus we only get non-zero malloced memory if that same page had something at those bytes before.
    → malloc can reuse freed memory

Calloc: Note there is also calloc, which allocates a zeroed block of memory. You hand it a number of elements and an element size.

  • slightly slower but less memory prone.

Realloc: we can also shrink / extend a block of memory realloc(void *ptr, size_t size)

  • allocations have a fixed size
  • always use the new address returned!
    • might copy the entire block to a new location!
  • contract does not guarantee anything (might be copied, extend in place, etc…)

free

Releases memory at the pointer.

  • must point to first byte at malloc’ed memory
  • after freeing → this memory region can be reused

Note: good practice to NULL after freeing
- CANNOT free memory twice

Note: we don’t need to specify a size → knows because malloc stores stuff

size_t and ptrdiff_t

size_t: (return type of sizeof)

  • unsigned inter of some size
  • guaranteed to be large enough to hold the size of the largest possible array in memory
    • can be used to store pointer

ptrdiff_t: a signed integer of some size, result of subtracting two pointers

  • used for array loops, size calculations

Heap

Malloc manages the heap space. It can run out (through memory leaks for ex).

GCed language can still have memory leaks → for example through cycles (but much less likely).

Structures and Unions

structs

p->x is short for (*p).x. We cannot just use .attr for a pointer to the struct.

Structs can be copied by assignment person1 = person2 → automatically copies for you.

  • this means you can pass a stuct by value!
  • This also means you can return a struct (not a pointer to a struct, but actually a struct).
void broken(struct point p) {
	p.x *= 2;
}
 
void works(strruct point *p) {
	p->x *= 2;
}

Can contain itself / pointer to itself → for trees for example

The struct name person for example → is a tag! It’s not the same namespace as a type!

Union

Union like a struct, but holds only one of a set of alternative values

  • accesses like a struct
  • no checking on which value
union u {
	int ival;
	float fval;
	char *sval;
};
union u my_uval; // can be any of int, float, char*

→ how do get which size this is?

typedef

typedef introduces a new type definition

  • new name for a type
  • can be used wherever original type could be
    → nice synonym / alias mechanism (can be recursively used)

typedef struct skbuf skbuf_t → instead of writing “struct skbuf” we can just write skbuf_t s.

  • some people think this is good idea
    using typedef for struct stuff
  • can even inline the struct definition in a typedef
  • or even recursive struct in there

Namespaces

  1. Label names
    1. see goto
  2. Tags
    1. one namespace for all structs, unions, enums
  3. Member Names
    1. one namespace for all structs, unions, enums
  4. Everything else (mostly)
    1. including typedef