We're sorry but this app doesn't work properly without JavaScript enabled. Please enable it to continue.

This lesson's interactive features are locked, please to keep using them

Trace

Click to play video

Now that we've done the first (and simplest) part: marking, we can trace through all of our objects and determine which ones are connected to the roots. For example:

def get_list():
    a = 5
    return [a]


print(get_list())

If we run this code it will return a list with the integer a inside of it. Our current mark function will mark the list, but it won't mark the integer a. Which means that when we go to sweep the memory, we will mark the list, but not the integer a. We'd then free a while it's still being used, and the operating system could then fill that memory with something else... which would be very bad!
So we need to prevent this!

But we also have another problem:

def get_list():
    a = []
    a.append(a)
    return [5]


print(get_list())

In the above (very dumb) example, we create a list that references itself and then return a completely unrelated list.

If our trace function looks for any object that is referenced by any other object it will consider a alive because it has a reference (albeit, to itself in this case). In fact, a is unreachable because when get_list returns, a is no longer used anywhere.

Tracing solves these problems. To be clear, tracing is part of the "mark" phase of mark and sweep. It's where we mark all the objects referenced by our root objects.

Assignment

This is one of the larger assignments, take your time. You're almost done with the course!