Lecture 2026-2-12

Check notes for intuition

Recall:

struct posn{
int* x;
int* y;
}
int main(){
*p.x = 3;
*p.y = 4;
}
  • Crashes (probably )

    • p.x + p.y are uninitalized ptrs

      • they point at arbitrary locations, dictated by whatever values they happen to hold ( in memory ).

        • Since this works in Racket, there MUST be something else happening

Drawing
  • So (posn 3 4) must also be reserving memory for x+y to point at, to hold the 3+4.

triangle-exclamation
circle-info

malloc(n) - requests n bytes of memory

  • Need to understand what's happening.

Memory Layout ( applies to C and Racket):

  • Static Area - Where global/static vars are stored.

    • Lifetime: entire program!

What is a stack?

  • An ADT (Abstract Data Type ) with LIFO (Last in, First out ) semantics

  • LIFO = last in, first out

    • can only remove the most recently inserted item.

  • Operations:

    • push - adds an item to the stack

    • top - what is the most recently inserted item?

      • pop - remove the most recently inserted item.

      • empty? - is the stack empty?

  • Racket lists are stacks:

    • push = cons

    • top = first

    • empty? = empty?

Program Stack ( THE Stack ) - stores local variables.

e.g.

Hence, in THE stack:

  • Each function call gets a stack frame ( see diagram )

    • Local vars are pushed onto the stack

    • also return address - WHERE to go when the function returns.

    • each invocation of the function get its own version of the local variables !!!

    • When a function returns, its stack frame is popped.

      • All local variables in thtat frame are released.

        • Not typically released.

  • "Top-of-stack" ptr moved to the top of the next frame.

    • frame will be overwritten the next time a frame is pushed onto the stack.

So what if you have data that must persist after the function reutrns?

e.g. What's wrong with:

⇒ Return

  • Returned p contains ptrs to local stack-allocated data.

    • DON'T DO THIS!

    • x+y (a+b ) will not survive past the end of makePosn!

  • malloc - request memory from the heap

    • pool of memory from which you explicitly request "chunks"

  • Lifetime of stack memory

    • Until the variable scope ends ( e.g. end of function )

  • Lifetime of heap memory - arbitrary

When makePosn returns,

  • p (incl p.x* p.y) popped off the stack - no longer live

    • 3 & 4 on the heap still live

  • p from makePos n copied back to main's frame.

    • main has access to 3 & 4 on the heap - these outlive makePosn

  • make-posn in Racket, does the same thing.

  • Lifetime of heap-allocated data is arbitrary long

  • If leap-allocated data never goes away, program will eventually RUN out of memory, even if the data in memory is no longer in use.

Racket Solution: A run-time process detects memory that is no longer accessible.

  • e.g.

  • Garbage Collection

C Solution: Heap memory is free'd when you free it.

  • Failing to free all allocated memory is called a memory leak.

Last updated