time_t Cast Away – Bits über Bord und der Y2K38 Bug ist zurück

Retro-Poster einer tropischen Insel mit Palmen, im Vordergrund ein Volleyball mit der Aufschrift „Y2K38“ im Sand. Darüber der Titel „Cast Away time_t“. Beschriftung (Caption):

Im Beitrag zu den Linux-Distributionen und Y2K38 haben wir gezeigt: viele Systeme sind heute grundsätzlich mit 64-Bit-time_t gerüstet und scheinbar vor dem Jahr 2038 Problem sicher. Doch die Epochalypse ist damit noch nicht endgültig abgewendet.

Denn „Cast Away“ heißt nicht nur Schiffbrüchiger oder etwas wegwerfen, sondern klingt für uns Entwickler:innen auch wie ein düsteres Wortspiel: etwas weg-casten. Genau das passiert im C-Code mit unbedachten Direct Casts. Mit (int)variable oder (long)variable werfen wir Bits über Bord – sie gehen verloren, verschollen wie Wrackteile nach einem Sturm.

Im Film Cast Away strandet Tom Hanks auf einer einsamen Insel. In unserem Fall stranden wir im Januar 2038 nicht auf einem Palmenstrand, sondern im Dezember 1901 – an einem Freitag, den 13. Kein Volleyball namens Wilson zum Reden, sondern nur ein Crash-Log, wenn wir Glück haben. Verursacht durch den „Cast Away“ der wichtigsten Bits in der Unix-Zeit.

Kurz erklärt: Was ist time_t?

time_t ist der Standard-Zeittyp in C und UNIX-Systemen. Er speichert die Anzahl der Sekunden seit dem 1. Januar 1970, 00:00:00 UTC – der sogenannten Unix-Epoche. Das Prinzip ist einfach: Zeit als fortlaufender Zähler.

Auf 32-Bit-Systemen wird time_t traditionell als vorzeichenbehafteter 32-Bit-Integer gespeichert. Damit endet der Zähler bei 2.147.483.647 Sekunden – exakt am 19. Januar 2038, 03:14:07 UTC. Der nächste Tick läuft über und springt ins Negative. Aus Zukunft wird Vergangenheit: das System glaubt, wir befänden uns plötzlich im Dezember 1901.

Auf 64-Bit-Systemen ist time_t meist 64 Bit breit. Damit reicht der Zähler für viele Milliarden Jahre. Rein rechnerisch würde er erst weit jenseits der Lebensdauer der Sonne überlaufen.

Wie auch im Artikel „Was ist der Y2K38-Bug?» erklärt, ist das eigentliche Problem also nicht die Unix-Epoche selbst, sondern die begrenzte Darstellungsbreite von time_t.

Die Rettung für Y2K38 am Horizont – oder nur eine Fata Morgana?

Als Lösung für die drohende Epochalypse gilt momentan die einfache Formel:
time_t wird auf 64 Bit erweitert, und das Problem ist vom Tisch. Auf 32-Bit-Systemen bedeutet das einen tiefen Eingriff in Betriebssystemen, Bibliotheken und Toolchains, weil viele Strukturen und Funktionsaufrufe sich ändern. Nebenbei entstehen dabei auch ABI-Probleme – inkompatible Schnittstellen, die sich aber mit sorgfältiger Migration in den Griff bekommen lassen.

Doch selbst wenn diese Umstellung technisch gelingt, könnten wir trotzdem Schiffbruch erleiden. Denn die eigentliche Gefahr lauert woanders – in unserem Code. Über Jahrzehnte haben sich zahllose direkte Casts angesammelt – (int)timestamp, (long)timestamp. Genau hier schlägt das Cast Away Problem zu. Jeder dieser Casts wirft Bits über Bord: Die frisch erweiterten 64-Bit-Zeitwerte werden wieder verkleinert und abgeschnitten. So holen wir uns den Y2K38-Bug durch die Hintertür zurück.

Die wahre Bedrohung liegt also in den Cast Aways, die den vermeintlichen Bugfix zunichtemachen und das Year 2038 Problem wieder zum Leben erwecken.

Direct Casts in C: Kein Fehler von Anfängern, sondern ein historisches Muster

Viele halten Direct Casts für Anfängerfehler – kleine Ausrutscher, die man eigentlich vermeiden sollte. Doch in Wirklichkeit sind sie tief in der Geschichte von C verankert. Oft dienten sie dazu, Compilerwarnungen zu beruhigen, alte APIs passend zu machen oder Speicher zu sparen. So sind über die Jahre unzählige Casts entstanden – absichtlich ins Meer der Codebasis geworfen und längst vergessen. Heute treiben sie dort wie Strandgut, bis sie 2038 wieder an Land gespült werden.

So etwas wie „unbedachte Fehler“ sind Direct Casts also nicht – sie haben sich aus der Praxis heraus entwickelt. Im Folgenden ein paar typische Beispiele, warum Entwickler:innen in C überhaupt gecastet haben.

Format-Strings und printf

Ein Klassiker für Direct Casts ist die Ausgabe mit printf. Da printf die Typen nicht prüft, führte schon ein falscher Format-String zu Warnungen oder falschen Ausgaben. Die schnelle Lösung: ein Cast.

Kompatibilität um jeden Preis

Viele ältere Bibliotheken und Schnittstellen erwarteten 32-Bit-Werte, auch wenn time_t breiter sein könnte.

Same Same but Different: int, long und time_t

Auf klassischen 32-Bit-Systemen waren int, long und oft auch time_t alle gleich groß – nämlich 32 Bit. Ein Cast zwischen diesen Typen wirkte daher harmlos und war gängige Praxis.

Arithmetic Cast Away: Rechnen mit der Zeit

time_t ist ein spezieller Typ, in vielen Implementierungen ursprünglich als long oder int definiert. Weil aber oft arithmetisch mit Zeitwerten gerechnet wird – etwa bei Differenzen oder Vergleichen – haben Entwickler:innen das Ergebnis von time() häufig in einen normalen Ganzzahltyp gecastet. Auf 32-Bit-Systemen war das unproblematisch, da alle Typen gleich groß waren.

Gleicher Cast, anderes Schicksal – gerettet oder gestrandet?

Ein Direct Cast sieht im Code immer gleich aus – doch sein Ergebnis hängt stark vom Datenmodell der Plattform ab. Beispiel: Unter Linux 64-Bit (LP64) ist long tatsächlich 64 Bit breit. Ein Cast wie (long)zeit wirkt dort harmlos. Unter Windows 64-Bit (LLP64) bleibt long jedoch 32 Bit – derselbe Cast kappt hier die oberen Bits.

Was also auf der einen Plattform völlig unauffällig erscheint, führt auf der anderen zum Schiffbruch. Genau deshalb sind Direct Casts so gefährlich: Sie sind nicht nur ein Problem des Codes, sondern auch eine Falle für die Portabilität.

Y2K38 Cast Aways – Hirngespinst oder reale Gefahr?

Hirngespinst wie Wilson, der Volleyball aus Cast Away, entstanden durch zu viel Sonne? Oder doch eine reale Gefahr, die uns mitten in die Epochalypse führen kann?

Schwierig zu sagen – aber ein Gefühl bekommt man, wenn man in öffentliche Repositories schaut: Eine einfache Suche nach dem Muster (int)time auf GitHub bringt über 100.000 Treffer. Und das ist nur die Spitze des Eisbergs.

Denn diese Suche erfasst weder alle anderen Varianten – (long)time(NULL), (unsigned int)time(), (size_t)time() – noch die unzähligen weiteren Casts, geschweige denn private und geschlossene Codebasen. Dazu kommen noch viele andere öffentliche Repositories jenseits von GitHub. Rechnet man all das zusammen, wird klar: Es muss Millionen von Casts geben, die time_t auf irgendeinen Integer-Typ herunterbrechen.

Die Cast Aways sind also kein Randphänomen, sondern real, weit verbreitet und längst Teil der Alltagskultur im C-Code.

Alles 64 Bit – und doch nicht gerettet

Die Erweiterung von time_t auf 64 Bit ist ein wichtiger Schritt, um die Epochalypse zu verhindern. Aber sie allein reicht nicht. Ein einziger unbedachter Cast genügt, um die mühsam erkämpfte Sicherheit wieder zunichtezumachen – und uns 2038 ins Jahr 1901 zurückzuwerfen.

Die eigentliche Gefahr liegt also nicht im Typ selbst, sondern in unserem Umgang damit.
Nur wenn wir Casts bewusst vermeiden, prüfen und absichern, bleibt time_t wirklich zukunftssicher – und unsere Systeme überstehen Y2K38 ohne Schiffbruch.

Nach oben scrollen