Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > de.alt.folklore.computer > #44683
| From | ram@zedat.fu-berlin.de (Stefan Ram) |
|---|---|
| Newsgroups | de.alt.folklore.computer |
| Subject | Re: Triumph of the Nerds |
| Date | 2024-05-13 09:49 +0000 |
| Organization | Stefan Ram |
| Message-ID | <Pointer-20240513103549@ram.dialup.fu-berlin.de> (permalink) |
| References | (13 earlier) <v17mad.2og.1@stefan.msgid.phost.de> <l9piqjFsmkrU9@mid.individual.net> <v1b88p.5g4.1@stefan.msgid.phost.de> <rf18hk-m5d.ln1@news.martinen.de> <v1srbq.5sk.1@stefan.msgid.phost.de> |
Stefan Reuther <stefan.news@arcor.de> schrieb oder zitierte:
>Am 13.05.2024 um 01:54 schrieb Kay Martinen:
>>Ich will jetzt nicht behaupten ich wüsste was Pointer genau machen, aber
>>es sind wohl Zeiger in einen Adressraum. Und das Problem besteht bei
>>einem Multitasking-system wohl darin das dies auch ein Fremder Prozess
>>sein könnte oder?
>Nein, denn der fremde Prozess nutzt einen anderen Adressraum.
Ich möchte hier einmal auf die Frage, was "Pointer genau machen"
zurückkommen.
Ein Zeiger ist eher ein Datum, er "macht" also nichts.
Was etwas "macht", ist ein Prozeß.
Was ein "Zeiger" genau ist, hängt von der Programmiersprache ab.
In der verbreitetesten Programmiersprache, Python, gibt es überhaupt
keine Zeiger. In der zweitverbreitetesten, C, gibt es aber Zeiger.
Die Definition von Zeigern in der Sprachnorm finde ich aber nicht
überzeugend, so daß ich hier etwas meine eigene Definition geben muß:
Zunächst einmal eine vereinfachte Definition, die aber für
viele Zwecke schon ausreicht:
Ein /Zeiger/ ist nichts anderes als eine /Adresse/.
Wenn man es dann etwas genauer sagen will, muß man hinzufügen,
daß ein Zeiger neben einer Adresse auch noch eine Information
über den /Typ und die Größe/ des Zieles enthält.
Nun etwas ausführlicher:
Wir müssen genauer zwischen /Zeigerwerten/ und /Zeigerobjekten/
unterscheiden: Meine Definitionen lauten dann:
- Ein Zeigerwert ist einen Wert eines Zeigertyps.
- Ein Zeigerobjekt ist ein Objekt eines Zeigertyps.
(Ein Objekt ist ein Speicher für Werte und hat einen Typ.
Die Relation zwischen Zeigerobjekten und Zeigertypen ist genauso
wie bei Objekten und Werten anderer Typen in C.)
Bei den Zeigerwerten müssen wir zwischen zwei Wertarten
unterscheiden:
- dem Nullzeiger und
- allen anderen Zeigern.
Bei den Zeigertypen müssen wir zweischen zwei Zeigertyparten
unterscheiden:
- Objektzeigertyparten und
- Funktionszeigertyparten.
Bei den Objektzeigertyparten müssen wir unterscheiden:
- dem Void-Zeiger-Typ und
- Nichtvoid-Zeiger-Typarten.
Einem Zeiger des Void-Zeiger-Typs fehlt die Information über den
Typ und damit über die Größe des Objektes an der Adresse des Zeigers.
Er entspricht damit einer reinen Adresse aus der Maschinensprache.
Schließlich muß man noch festhalten, daß es eine zentrale
Operation für Zeiger gibt, nämlich die Dereferenzierung "*".
Mehr dazu folgt.
Dann können wir sagen:
- Ein Zeigerobjekt enhält einen Zeigerwert.
- Der Nullzeiger darf nicht dereferenziert werden.
- Ein Wert des Void-Zeiger-Typs darf auch nicht
dereferenziert werden.
- Die Dereferenzierung eines Funktionszeigers, der kein
Nullzeigerwert ist, ergibt im Prinzip eine Funktion.
- Die Dereferenzierung eines Objektzeigers, der kein
Nullzeigerwert ist und keinen Void-Zeiger-Typ hat,
ergibt ein Objekt. Der Typ jenes Objekts, und damit
seine Größe, ist bereits zur Übersetzungszeit bekannt.
Beim letzten Satz gibt es jedoch eine Anmerkung: Es ist möglich,
daß Speicher /dynamisch alloziert/ wird, und dann ist dessen
allozierte Größe nicht mehr notwendigerweise der Größe jenes
Objekttyps aus dem vorigen Satz gleich.
Bei der dynamischen Allozierung wird die Berechtigung zur Nutzung
eines Speicherbereichs angefordert und der Speicherbereich ergibt
sich dann als ein Void-Zeiger (ein Wert des Void-Zeiger-Typs).
Die korrekte Beachtung der allozierten Größe ist dann eines
der Probleme bei der Programmierung. Andere Probleme sind der
korrekte Umgang mit dem Nullzeiger und die korrekte Paarung
von Allokationen und Freigaben von zur Laufzeit alloziertem
Speicher innerhalb eines Programms.
Bei der Programmierung in /Maschinensprache/ hat man jedoch
die meisten dieser Problem /genau so/, außerdem jedoch noch
etwas weniger Hilfe, weil dort das Typsystem ganz fehlt.
>Eine Programmiersprache, die Speichersicherheit durchsetzt, ist sicher
>ein Fortschritt gegenüber einer, die das nicht tut. Nur verführt das
>halt zu der Ansicht "ich habe einen Garbage Collector und nun bin ich
>alle meine Probleme los und muss mich um nichts mehr kümmern". Das ist
>eben nicht so.
Es werden nicht alle Probleme gelöst, aber es ist ein großer
Fortschritt. Praktische funktionale Programmierung ist ohne
GC praktisch nicht möglich.
>Abstrahiert betrachtet ist ein Pointer nur ein Bitmuster, das eine
>Ressource beschreibt.
Was ein "Pointer" ist, hängt von der Sprache ab. In C ist
er nicht nur die Adresse, sondern hat eben manchmal auch
noch Typinformation, welche manchmal die Größe liefert. Bei
alloziertem Speicher, liefert jener Typ aber nicht mehr korrekt
die Größe, so daß ein Zeiger dann wieder mehr nur das ist,
was er auch in Maschinensprache ist, nämlich eine Adresse.
>Entweder man lässt das den GC über Finalizer machen (deprecated
>feature), dann führt das dazu, dass der Jenkins nach dem RAM-Upgrade mit
>"too many open files" stirbt, weil der GC seltener aufräumt.
Also ich glaube, es wurde schon vor längerer Zeit (10, 20 Jahren)
darauf hingewiesen, daß man sich in Java auf "Finalizer" als
Wege zur Verwaltung von Ressourcen nicht verlassen soll. Aber
hier geht es dann eben um die Verwaltung anderer Typen von
Ressourcen (wie Dateien) und nicht mehr von Speicherblöcken.
Back to de.alt.folklore.computer | Previous | Next | Find similar | Unroll thread
csiph-web