Lecture 2026-2-24

Null pointers, undefined behaviour, dynamic arrays, linked-lists (in C, akin to Racket Lists), List Proccess

You will fail test-cases if you have memory-leaks.

Recall:

int *p = malloc(...);
free(p);
failing to free all allocated memory - called a memory leak.
int *p = malloc (....);
free (p);
*p = 7;//will this crash? code

  • probably not since free(p) doesn't change p

    • p still points to that memory, so storing there unlikely to crash - but the location can be given out to another malloc call -> data corruption

  • called a dangling pointer. BAD

Better: after free(p), assigns p to a guaranteed-invalid location

int *p = malloc(____);
free(p);
p = NULL; // null pointer - points to nothing
circle-info

NULL is NOT part of the C language.

  • it is defined as a constant ( in the library )equal to 0.

  • Could equally well say p = 0;

Thus now, p does NOT point to anything.

Deferencing NULL

  • Undefined behaviour ( UB )

  • program may crash ( when will it NOT crash )

If malloc fails to allocate memory- returns NULL.

e.g.

Consider again:

  • Think of the stackframe.

circle-info

Thus, programs might not crash- but will behave badly.

e.g.

  • 5 replaces 4

  • data corruption

circle-info

Never return a pointer to a local variable.

circle-info

If you want to return a pointer, it should point to static, heap, or non-local stack data.

because THEY DON'T go away !

circle-info

Use the heap:

  1. For data that should outlive the function that creates it ( when to use static, when to use malloc)

  2. For data whose size is not known at compile-time

  3. For large local arrays.

1) as above ( getMeaPtr)

2)

  • What if we ask for more memory (arg does NOT have to be constant)?

This leads to dynamic arrays ( why? )

  • can acess `p[0],...,p[numSlotsNeeded -1]

    • dynamic array ( heap-allocated)

.....free(p)

  1. Programs typically have more heap memory than stack memory.

This was akin to replicating Racket-like Structs in C ( How?)

Can we get the behaviour of a Racket list in C?

(cons x y) produces a pair x[<- ][->]y ( pointers )

Recall: Racket is dynamically typed.

C is statically typed ⇒ list items would need to have the same type.

(if not ⇒ headache)

  • So no actual need for ptrs to datafields ( as they were there bc of different types )

Thus how does one "process" a linked list?

OR

Can we write map ( FAVOURITE FUNCTION )

circle-info

You can pass functions as arguments in functions. But what happens?

  • The name of a function is a pointer to the function's code.

  • But note, we have the name and name-definition, but we don't have environment

  • Due to the "flat-environment" of C, we can get away, sometimes, by NOT using an environment.

    • Reveals the power of Racket and limitations of C compared to Racket.

But what does f look like?

  • Since we know that the code coming in we can easily make declaration, and go from there:

    • We read C declaration from variable then goes outwards, smth smth smth.

      • Thus int * f(int) , from postfix before prefix, we have a declaration of a function that passes an int and returns a pointer to an int ( int * ).

circle-info

Exercise: Do it iteratively.

Freeing Linked Lists.

  • cur = cur -> next happens after free (cur)

  • cur is dangling

  • need to grab next pointer before you free.

    • How do you do that?

  • we are def getting a problem that asks if a pointer is dangling.

Last updated