🔧 AI Nachrichten GenAI Workflows für Social Media Content(02.09.2026 um 14:00 Uhr)
🪟 Windows Tipps<b>Windows</b> - IT-Administrator.de(04.09.2026 um 04:17 Uhr)
🔧 AI Nachrichten GenAI Workflows für Social Media Content(02.09.2026 um 14:00 Uhr)
⚠️ Malware / Trojaner / VirenLumma Stealer – dllhost.exe Hollowing, C2 Domains &amp; Payload Extraction(01.09.2026 um 17:19 Uhr)
🔧 AI Nachrichten Simcha Kosman AMA: Owning ChatGPT's Secure Sandbox(03.09.2026 um 07:41 Uhr)
⚠️ Malware / Trojaner / VirenThe Gentlemen Ransomware Analysis: Go Obfuscated(04.09.2026 um 12:05 Uhr)
🔧 AI Nachrichten GenAI Workflows für Social Media Content(02.09.2026 um 14:00 Uhr)
🪟 Windows Tipps<b>Windows</b> - IT-Administrator.de(04.09.2026 um 04:17 Uhr)
🔧 AI Nachrichten GenAI Workflows für Social Media Content(02.09.2026 um 14:00 Uhr)
⚠️ Malware / Trojaner / VirenLumma Stealer – dllhost.exe Hollowing, C2 Domains &amp; Payload Extraction(01.09.2026 um 17:19 Uhr)
🔧 AI Nachrichten Simcha Kosman AMA: Owning ChatGPT's Secure Sandbox(03.09.2026 um 07:41 Uhr)
⚠️ Malware / Trojaner / VirenThe Gentlemen Ransomware Analysis: Go Obfuscated(04.09.2026 um 12:05 Uhr)

26 🕛 kürzlich 5 Min Lesezeit
0

Ghost in the Stack (Part 1): Why uninitialized variables remember old data

↗ Quelle (dev.to)
🗣️ Stimme:
📑 Inhaltsübersicht

Have you ever written a C program, run it, and watched it print values you never assigned?

At first glance, it feels almost as if old data is haunting your program from beyond a function call, but what is happening under the hood is far more interesting:




  • stack frame reuse


  • compiler behaviour


  • memory persistence


  • and the performance tradeoffs built into modern systems




In this series, we'll go from high-level C code into stack frames, assembly instructions, and eventually real-world security implications.

Today, in Part 1, we investigate one of the most common low-level surprises in C: uninitialized local variables appearing to "remember" old values.

Consider the following program:




CODE
#include <stdio.h>
void Subtraction()
{
int a = 100;
int b = 35;
int c = a - b;
}
void PrintValues()
{
int i, j, k;
printf("First value is %d\nSecond value is %d\nThird value is %d\nThese are the values for PrintValues function\n", i, j, k);
}
int main()
{
Subtraction();
PrintValues();
return 0;
}






If we compile without optimization: gcc -O0 main.c, we may observe output similar to this:




CODE
First value is 100
Second value is 35
Third value is 65
These are the values for PrintValues function






At first glance, this looks impossible. PrintValues never initializes its variables. So why does it print the exact same values previously used by Subtraction()? Important Warning: This is undefined behaviour

Before going deeper, we need to clarify something important.

Reading uninitialized local variables in C is undefined behaviour.

That means:




  • the C standard does not guarantee what happens


  • different compilers might behave differently


  • optimization levels may change the result


  • future executions may produce different outputs

    The behaviour shown above is simply one possible outcome observed under a particular compiler configuration.






The Dirty Whiteboard Analogy



To understand what's happening, forget the code for a moment. Imagine RAM as a whiteboard in a shared classroom. First teacher (Subtraction()). A math teacher walks into the room and writes: 100, 35, 65 on the whiteboard. After class ends, she leaves without erasing anything, because erasing takes time. For a brief moment, the room is empty. The writing is still visible. Nothing has overwritten it yet. Second teacher (PrintValues()). A history teacher enters the room immediately afterward. Instead of writing anything new, he simply reads whatever is already on the board. At a high level, this resembles what happens with stack memory. When a function returns, typical compiled code does not automatically erase the stack bytes previously used for local variables. Instead:




  • the stack space becomes available for reuse


  • old data often remains there temporarily


  • another function may reuse the same stack offsets

    If the new function reads memory before writing new values, it may accidentally observe leftover bytes from an earlier stack frame.






INSPECT THE ASSEMBLY FOR SUBTRACTION()



Let's inspect the assembly generated for Subtraction(). Below is the disassembly produced by GDB on x86-64:




CODE
push %rbp
mov %rsp,%rbp
sub $0x30,%rsp
movl $0x64,-0x4(%rbp)
movl $0x23,-0x8(%rbp)
mov -0x4(%rbp),%eax
sub -0x8(%rb),%eax
mov %eax,-0xc(%rbp)
mov -0xc(%rbp),%ecx
mov -0x8(%rbp),%edx
mov -0x4(%rbp),%eax
add $0x30,%rsp
pop %rbp
ret






push %rbp - Save the base pointer onto the stack

mov %rsp,%rbp - Set the stack pointer as the base pointer.

sub $0x30,%rsp - Allocate 48 bytes of space on the stack

movl $0x64,-0x4(%rbp) - Store 100 into the first 4 bytes on the stack

movl $0x23,-0x8(%rbp) - Store 35 into the second slot

mov -0x4(%rbp),%eax - Load 100 into the eax register

sub -0x8(%rbp),%eax - Subtract 35 from eax, the result remains in eax

mov %eax,-0xc(%rbp) - Move the result from the register to memory

mov -0xc(%rbp),%ecx - Move to register

mov -0x8(%rbp),%edx - Move to register

mov -0x4(%rbp),%eax - Move to register

add $0x30,%rsp - Clean up allocated stack space

pop %rbp - Restore the previous stack frame

ret - Return control to the caller

After the function returns, the stack frame is released. The stack pointer simply moves back, making that region available for reuse. The previous values often remain there temporarily until another operation overwrites them. Typically compiled code does not automatically clear old stack contents because doing so would introduce additional instructions and reduce performance.





ENTER PrintValues()



Now let us examine the beginning assembly code generated for PrintValues()




CODE
push %rbp
mov %rsp,%rbp
sub $0x30,%rsp
mov -0xc(%rbp),%eax
mov -0x4(%rbp),%edx
mov -0x8(%rbp),%ecx






Notice something very important. PrintValues() allocates a very similar stack layout. So this instruction:

mov -0x4(%rbp),%eax means read whatever bytes that exists here. If those bytes still contain leftover data from Subtraction(), then PrintValues() may appear to "remember" the earlier values.

This teaches something deeper than uninitialized variables are dangerous. It reveals an important systems principle: memory is reused, not automatically cleaned.

Vollständiger Original-Bericht
Ausführliche Details, Code-Beispiele & Hersteller-Stellungnahme auf dev.to.
↗ Original-Artikel auf dev.to lesen
Wie bewertest du diesen Beitrag?
1 Klick Feedback
Teilen mit Netzwerk & Team:

Community-Analysen & Experten-Meinungen 0

Verfasse deine eigene Analyse, teile Workarounds oder diskutiere diesen Vorfall im Blog.
Noch keine Community-Analyse verfasst. Markiere einen Textabschnitt oder klicke oben auf Eigene Analyse verfassen“!
Community Pulse: Relevanz-Einschätzung
1 Klick Experten-Votum
🔴 Akute Relevanz 56%
🟡 In Evaluierung 27%
🟢 Keine Auswirkung 12%
Spannende Innovation 5%
Verwandte Story-Cluster & Quellen (Vektor-KI)
Port 8095 Engine
1 Quelle
Ungentlemanly behavior: Insights into a ransomware operation
1 Quelle
SonicWall 83548 83549
1 Quelle
Government, industry partner to shut down long-running Sality botnet
Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten Ghost in the Stack (Part 1): Why uninitialized variables remember old data

Thematisch verwandte Begriffe: Ghost, Stack, Part, uninitialized · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...