
Hello fellow sloths!
Welcome to this week’s Sloth Bytes. I hope you had an amazing week! 😁

Your career will thank you.
Over 4 million professionals start their day with Morning Brew—because business news doesn’t have to be boring.
Each daily email breaks down the biggest stories in business, tech, and finance with clarity, wit, and relevance—so you're not just informed, you're actually interested.
Whether you’re leading meetings or just trying to keep up, Morning Brew helps you talk the talk without digging through social media or jargon-packed articles. And odds are, it’s already sitting in your coworker’s inbox—so you’ll have plenty to chat about.
It’s 100% free and takes less than 15 seconds to sign up, so try it today and see how Morning Brew is transforming business media for the better.

What Is Memory and Why Does It Leak?

Ever wondered why a long-running server slowly eats more memory, or why a game’s memory footprint keeps climbing after repeatedly loading and unloading the same level? A memory leak is one possible cause—but rising RAM usage can also come from intentional caches, fragmentation, allocator behavior, or a workload that genuinely needs more live data.
5 bytes in 1 blocks are definitely lost in loss record 1 of 1Congrats, you've met the memory leak!
One of programming's silent killer.
Let's talk about what memory actually is, why it "leaks," and how to stop your programs from becoming digital hoarders.
Memory: Your Program's Workspace
Think of your computer's memory (RAM) like a massive whiteboard. When your program runs, it writes stuff on the board:
name = "Sloth" # Write "Sloth" on the board
score = 100 # Write "100" somewhere else
inventory = ["sword"] # Write a list over hereUnlike your hard drive (permanent storage), RAM is temporary. When your program ends, the whole whiteboard gets erased. Fresh start.
The Problem: Memory leaks
The term "Memory leak" is misleading.
The memory usually isn’t leaking out of the computer. A leak means resources remain allocated or objects remain reachable even though the application no longer needs them, so that memory cannot be reclaimed for future useful work.
In manually managed languages, code may forget to release an allocation. In garbage-collected languages, the collector can only free objects that are no longer reachable—so accidentally keeping a reference can retain an entire object graph.
“But my language has garbage collection 🤓 👆 “
Garbage collection (gc) does handle a lot of the cleanup work for you!
Usually…
However you can still leak memory by keeping references (hoarding):
all_results = []
def analyze_data(filename):
huge_data = load_file(filename) # Pretend it's 500MB
result = process(huge_data)
all_results.append(huge_data) # Why keep this?
return result
# We never remove the data from all_results...Each file keeps another huge object reachable through all_results. If the application never needs those inputs again and the list grows without bound, that’s a classic retention leak / unbounded retention.
The garbage collector cannot reclaim the objects because the global list still points to them. From the runtime’s perspective, they are still live.
Your program is now a digital hoarder, keeping everything "just in case."
Common Memory Leak Patterns
The Unbounded Cache (Java example):
class Cache {
private final Map cache = new HashMap<>();
void put(String key, Data value) {
cache.put(key, value); // No size limit, TTL, or eviction policy.
}
}A cache is not automatically a leak. It becomes a memory problem when retention is unbounded relative to the workload. Real caches need some combination of size limits, TTLs, eviction, weak references, or explicit invalidation depending on the use case.
The Forgetter:
void processFile() {
char* buffer = malloc(1000000);
// We forgot to free(buffer)!
}The Reachability Trap:
callbacks = []
class Screen:
def __init__(self, name):
self.name = name
def on_event(self):
print(self.name)
screen = Screen("settings")
callbacks.append(screen.on_event)
# Later the UI "closes" the screen...
screen = None
# ...but callbacks still holds a bound method, which keeps the Screen alive.Circular references by themselves are not automatically leaks. Modern tracing garbage collectors such as Python’s can collect many unreachable cycles. The important question is whether something that is still reachable—like a global registry, listener, timer, cache, closure, or native handle—keeps data alive longer than intended.
Common fixes to memory leaks
1. Release resources deterministically
# Context managers guarantee the file handle is closed.
with open("file.txt", encoding="utf-8") as f:
data = f.read()File handles, sockets, locks, database connections, GPU buffers, and other OS/native resources are not the same thing as managed heap memory, but leaking them can be just as destructive. Use language/runtime cleanup mechanisms such as context managers, defer, RAII, finally, or explicit close/free APIs.
2. Bound caches and collections
from collections import OrderedDict
class LRUCache:
def __init__(self, max_size=1000):
self.max_size = max_size
self.data = OrderedDict()
def put(self, key, value):
if key in self.data:
self.data.move_to_end(key)
self.data[key] = value
if len(self.data) > self.max_size:
self.data.popitem(last=False)Production code will usually use a maintained cache implementation, but the principle is the important part: define how much can be retained and when it leaves.
3. Pair manual allocations with ownership
char* buffer = malloc(1000);
if (buffer == NULL) {
/* handle allocation failure */
}
/* use buffer */
free(buffer);
buffer = NULL; /* avoids accidentally reusing this pointer variable */Setting this local pointer to NULL does not free anything by itself—the free() call does. In C/C++, clear ownership rules and RAII/smart pointers where appropriate reduce mismatched allocation/free paths.
4. Unsubscribe listeners and cancel long-lived work
const timer = setInterval(check, 1000);
const handler = () => refresh();
window.addEventListener('resize', handler);
// When the component/job is disposed:
clearInterval(timer);
window.removeEventListener('resize', handler);Timers/listeners can retain closures and object references. Whether that becomes a leak depends on lifecycle: a timer intentionally running for the entire process is fine; one accidentally created on every screen mount and never removed is not.
Why Should You Care?
A leak in a short-lived process may never become noticeable because the operating system reclaims the process’s resources when it exits. In long-running services, games, desktop apps, workers, and embedded systems, retention bugs have time to accumulate.
But in long-running programs (servers, games, desktop apps, embedded systems), those leaks add up:
Game starts at 60 FPS, drops to 15 FPS after 2 hours
Server crashes every few days
Your Arduino project “mysteriously” stops working
Desktop app using 8GB of RAM for no reason
How to Spot a Leak
Possible symptoms:
The live heap / retained-object count grows after repeating the same workload.
Memory does not stabilize after traffic/workload returns to a previous level.
Garbage collection becomes more frequent/expensive.
The process eventually hits a memory limit, swaps heavily, or is killed.
Do not assume “RSS went up and did not immediately go down” proves a leak. Runtimes and allocators often keep freed pages for reuse instead of returning them to the OS. Compare heap/allocation snapshots and retained objects across repeated, representative workloads.
Helpful Tools
System metrics: Task Manager / Activity Monitor / container metrics for a quick trend—not proof by itself.
Python: built-in
tracemallocfor allocation snapshots; tools such as Memray for deeper profiling.JavaScript: browser/Node heap snapshots and allocation profiles.
Java: heap dumps, Java Flight Recorder, JDK Mission Control, VisualVM.
C/C++: Valgrind, AddressSanitizer/LeakSanitizer, platform heap profilers.
The Bottom Line
A useful mental model is: a memory leak is memory/resources kept alive longer than intended, with no bounded lifecycle. The cause might be a missing free(), a global reference, an unbounded cache, a forgotten listener, a native handle, or another ownership/lifecycle bug.
Watch out for:
Collections/caches with no bounds or eviction
Global registries and callbacks that retain dead objects
Forgotten native resources such as files/sockets/connections
Listeners, observers, subscriptions, and timers not removed with their owner
Manual allocations whose ownership/free path is unclear
Garbage collection prevents many manual-memory bugs, but it cannot know that a reachable object is logically useless to your application.
So don’t ask only “did I allocate memory?” Ask: what owns this object/resource, how long should it live, and what event releases it?
If you want to keep learning
Code profiling explained — use memory profilers to find which allocations keep growing and where the leak actually starts.
Debugging techniques — reproduce and isolate the behavior before changing random parts of your code.
Big O notation explained — understand the difference between code that scales badly by design and code that is leaking resources over time.


Thanks for the feedback!



Thanks to everyone who submitted!
andregarcia0412, bakzkndd, Kauketz, xanerin, jw123450, LaurelineP, mau-estradiote, SabhyaAggarwal, ariatheroyal, Sorbojit1, vmillios, and RelyingEarth87.
Next in the Alphabet
Create a function which returns the next letters alphabetically in a given string. If the last letter is a "Z", change the rest of the letters accordingly.
Examples
next_letters("A")
output = "B"
// 'A' becomes 'B' – simple increment.
next_letters("ABC")
output = "ABD"
// 'C' becomes 'D' – last character changes without carry.
next_letters("Z")
output = "AA"
// 'Z' rolls over to 'A', and since there's no previous letter, we add a new 'A'.
// Think of it like 9 + 1 = 10, here Z + 1 = AA.
next_letters("CAZ")
output = "CBA"
// 'Z' → 'A' (carry), 'A' → 'B' (no carry), so "CAZ" becomes "CBA".
// Like incrementing 129 → 130 but in letters.
next_letters("")
output = "A"
// Empty input is treated as 0 → return 'A'.Notes
Tests will all be in CAPITALS.
Empty inputs should return a capital "A" (as if it were in letter position 0!).
Think about the letter "Z" like the number 9 and how it carries over to increment the next letter/digit over.
How To Submit Answers
Reply with
A link to your solution (github, twitter, personal blog, portfolio, replit, etc)
or if you’re on the web version leave a comment!
If you want to be mentioned here, I’d prefer if you sent a GitHub link or Replit!

New video this week hopefully!
Recently hired an editor, so I’m hoping I can start uploading consistently 😃
That’s all from me!
Have a great week, be safe, make good choices, and have fun coding.
If I made a mistake or you have any questions, feel free to comment below or reply to the email!
See you all next week.
What'd you think of today's email?
Want to advertise in Sloth Bytes?
If your company is interested in reaching an audience of developers and programming enthusiasts, you may want to advertise with us here.







