[an error occurred while processing this directive]

Einführung in die getrennte Übersetzung und das Binden (Linken) von Zwischendateien im Rahmen der Lehre der Programmierung. [] (Binder, Linker), Lektion, Seite 720570
http://www.purl.org/stefan_ram/pub/programmieren_getrennte_uebersetzung_de (Permalink) ist die kanonische URI dieser Seite.
Stefan Ram

Getrennte Übersetzung

Da Quelltext von einem Prozessor oft nicht direkt ausgeführt werden kann, muß er in eine Zielsprache  übersetzt werden, also in eine Sprache, die der verwendete Prozessor versteht, und in das Format gebracht werden, das das Zielsystem (Betriebssystem) für ausführbare Dateien vorschreibt, wenn ein ausführbares Programm (Endprodukt) erzeugt werden soll.

Bei der Herstellung eines Software-Produktes werden oft mehrere  Übersetzungseinheiten verwendet. Diese werden dann getrennt  (also jeweils einzeln) kompiliert (übersetzt) werden. Der Übersetzungsvorgang einer einzelnen Übersetzungseinheit erzeugt dann noch nicht das Endprodukt, sondern ein Zwischenprodukt  (eine Zwischendatei  oder Zwischeneinheit ), das manchmal auch als Montageobjekt, Objektdatei  oder als Klassendatei  bezeichnet wird. Diese Zwischeneinheiten können dann schließlich durch ein weiteres Programm, den Verbinder  (auch: Binder, engl.: “linker ”) zu einem verwendbaren Endprodukt  verbunden werden.

Die Aufteilung eines Programmes in mehrere Übersetzungsdateien ist besonders bei größeren  Programmen hilfreich. In einführenden Lehrgängen zu einer Programmiersprache werden aber anfangs zunächst nur kleinere Programme geschrieben. Daher können Techniken zur Bewältigung größerer Projekte in Lehrgängen nicht immer durch entsprechende Beispiele motiviert werden. Die Kenntnis dieser Techniken ist jedoch für die Praxis nötig, da das Hauptproblem bei der Software-Erstellung gerade die Bewältigung der Komplexität größerer Projekte ist.

Eine Zwischendatei ist schon weitgehend in die ausführbare Zielsprache übersetzt, ist aber alleine noch nicht ausführbar, da ihr noch Programmteile fehlen, die an anderen Stellen definiert wurden, und auch ihr Format noch nicht den Vorgaben des Zielsystems für ausführbare Dateien entsprechen muß.

getrennte Uebersetzung [Datenflußplan]
        _____                    _____                    _____ 
.-' '-. .-' '-. .-' '-. 
.' '. .' '. .' '. 
/ \ / \ / \ 
; Uebersetzungs- ; ; Uebersetzungs- ; ; Uebersetzungs- ; 
| Einheit | | Einheit | | Einheit | 
; 0 ; ; 1 ; ; 2 ; 
\ / \ / \ / 
'. .' '. .' '. .' 
'-._____.-' '-._____.-' '-._____.-'  
| | | 
V V V 
.-------------------. .-------------------. .-------------------. 
| | | | | | 
| Uebersetzer | | Uebersetzer | | Uebersetzer | 
| | | | | | 
'-------------------' '-------------------' '-------------------' 
| | | 
__V__ __V__ __V__ 
.-' '-. .-' '-. .-' '-. 
.' '. .' '. .' '. 
/ \ / \ / \ 
; Zwischen- ; ; Zwischen- ; ; Zwischen- ; 
| Produkt | | Produkt | | Produkt | 
; 0 ; ; 1 ; ; 2 ; 
\ / \ / \ / 
'. .' '. .' '. .' 
'-._____.-' '-._____.-' '-._____.-' 
| | | 
'---------------------. | .---------------------' 
| | | 
| | | 
V V V 
.-------------------. 
| | 
| Verbinder | 
| | 
'-------------------' 

__V__ 
.-' '-. 
.' '. 
/ \ 
; End- ; 
| Produkt | 
; ; 
\ / 
'. .' 
'-._____.-'

Statt mehrerer Übersetzungseinheiten (Quellen, Quelldateien) könnte auch eine einzige großen Übersetzungseinheit verwendet werden. Doch die Aufteilung einer großen Übersetzungseinheit in mehrere getrennte kleinere Übersetzungseinheiten hat verschiedene Vorteile.

Bezüge

Eine Entität, die in einer Übersetzungseinheit definiert wurde, kann oft von einer anderen Übersetzungseinheit verwendet werden. Dabei wird die Verwendung den Bezug in der Regel über den öffentlichen Namen  der Entität herstellen. Ein öffentlicher  Name kann von anderen  Übersetzungseinheiten aus verwendet werden, während ein privater Name  (interner Name ) nur innerhalb  seiner Übersetzungseinheit definiert ist und von anderen Übersetzungseinheiten aus nicht bemerkt wird, so daß er dort beispielsweise auch wieder mit einer ganz anderen Bedeutung als interner Name verwendet werden könnte. Insofern sind Übersetzungseinheiten Namensräume ihrer privaten Namen.

In einer Übersetzungseinheit kann also ein öffentlicher Name für eine Entität definiert werden und in anderen Einheiten kann dann dieser öffentlicher Name verwendet werden, um sich auf diese Entität zu beziehen. Innerhalb eines Projektes aus mehreren Übersetzungseinheiten, darf ein öffentlicher Name im allgemeinen nur einmal  in einer einzigen Übersetzungseinheit definiert werden (one definition rule ), aber er darf beliebig oft in allen Übersetzungseinheiten verwendet werden, um sich auf seine Definition zu beziehen.

Im dem durch die Übersetzung erzeugten Zwischenprodukt wird dann ebenfalls noch die Bezugnahme des Quelltextes auf die Entität vorhanden sein, die in einem anderen Zwischenprodukt definiert sein kann. Solange die beiden Zwischenprodukte noch getrennt voneinander sind, spricht man von einer unaufgelösten Bezugnahme (Referenz), da in dem Zwischenprodukt mit der Referenz die referenzierte Entität noch fehlt.

Bezug in einem Zwischenprodukt
.------------------------.             
| Zwischenprodukt 0 |  
|------------------------|  
| |  
| ... | .------------------------. 
| | | Zwischenprodukt 1 | 
| | |------------------------| 
| | | | 
| | | ... | 
| | | | 
|------------------------| |------------------------| 
| Bezug auf "kuckuck" -------> | Definition von | 
|------------------------| | "kuckuck" | 
| ... | |------------------------| 
'------------------------' | ... | 
| | 
| | 
| | 
'------------------------'

Durch das Verbinden  der beiden Zwischenprodukte gelangen die Bezüge  auf eine Entität und die Definition  der Entität dann in eine einzige Datei (Einheit). Der Namensbezug wird dabei oft durch einen effizienteren Bezug, wie einen Adreßbezug, ersetzt. Das heißt, daß statt des Namens die Entität nun durch ihre Position  (Adresse ) in dem Produkt bestimmt wird und auch Bezugnahmen über diese Position erfolgt. Der Verbinder ersetzt die Namen also überall durch Adressen. Solche Adreßbezüge können dann von der ausführbaren Zielsprache direkt verarbeitet werden und dies ist auch schneller möglich als bei Namensbezügen, da die Adressen sofort verwendet werden können, während zu einem Namen erst die passende Adresse gesucht werden müßte. So entsteht schließlich eine Datei, die keine Bezüge auf externe Definitionen mehr enthält.

Bezug im Endprodukt
.------------------------. 
| Endprodukt | 
|------------------------| 
| | 
| ... | 
| | 
|------------------------| 
| Bezug auf Entität | 
| bei Adresse 4321 | 
|----------|-------------| 
| | | 
| ... | | 
| V | 
|------------------------| 
| 4321: Implementation | 
|------------------------| 
| | 
| ... | 
| | 
'------------------------'

Die Namen von Entitäten des Quelltextes, wie beispielsweise Routinen, sind in dem erzeugten Endprodukt daher oft gar nicht mehr enthalten. Das erklärt, warum beispielsweise eine Routine, die die Namen aller Routinen eines Programmes ausgibt, in vielen Programmiersprachen nicht geschrieben werden kann (es sei denn alle Namen werden noch einmal getrennt erfaßt): Diese Namen sind in dem fertigen Programm nicht mehr enthalten. Es wird auch verständlich, warum es nicht möglich ist, aus einem ausführbaren Programm den Quellcode wiederzugewinnen: Bestimmte Informationen, wie die Namen der Entitäten, sind nicht mehr im Endprodukt enthalten und können deswegen daraus auch nicht wiederhergestellt werden.

Ein Verbinder kennt auch das Format, in dem ein Betriebssystem ausführbare Dateien erwartet, und kann das Endprodukt entsprechend so erzeugen, daß es auf dem Zielsystem direkt als Programm gestartet werden kann.

Wie ein Verbinder genau bedient wird, hängt vom verwendeten Programm ab und wird nicht in dieser Lektion behandelt. Unter vielen Entwicklungsumgebungen reicht es aber, zusammengehörige Quelldateien als ein Projekt zu kennzeichnen und den Typ des gewünschten Endproduktes anzugeben, damit die aus ihnen erzeugten Zwischenprodukte zu dem gewünschten Endprodukt verbunden werden.

Bibliotheken

Ein großer Vorteil der getrennten Kompilierung ist es ja, daß eine nützliche Übersetzungseinheit zur Herstellung verschiedener  Projekte verwendet werden kann. Man kann hierbei noch einen Schritt weitergehen und daran denken, eine nützliche Übersetzungseinheit sogar an verschiedene andere Personen weiterzugeben, so daß auch andere diese nutzen können.

Solch eine Sammlung nützlicher Entitäten wird auch als eine Bibliothek  (engl. library ) bezeichnet. Eine Bibliothek kann aus mehreren Zwischenprodukten bestehen, die dabei sozusagen die Rolle der „Bücher“ spielen. In einer Übersetzungseinheit können dann die Entitäten der Bibliothek so verwendet werden, wie auch in einer anderen Übersetzungseinheit definierte Entitäten.

Nicht immer müssen zum Lieferumfang einer Bibliothek auch die Quelldatei (Übersetzungseinheiten) gehören, es reicht ja wenn die Zwischendateien und eine Erklärung (Dokumentation) der in ihnen definierten Entitäten ausgeliefert wird. So hat der Hersteller einer Bibliothek auch einen gewissen Schutz seines Quellcodes vor ungewünschten Analysen durch Verwender der Bibliothek.

Eine bestimmte Bibliothek gehört zu den meisten Programmiersprachen und umfaßt eine Sammlung vordefinierter Standardentitäten. Weitere Bibliotheken können aus verschiedenen Quellen bezogen werden, manche sind kostenlos erhältlich, andere müssen gekauft werden, zu manchen ist der Quellcode kostenlos erhältlich, zu anderen ist es gegen eine Aufpreis oder gar nicht lieferbar.

Dadurch, daß die Bibliotheken dann mit den Zwischendateien eines Projektes verbunden werden, entsteht schließlich das fertige Endprodukt. Dabei werden die Teile der Bibliothek, die in den Zwischendateien verwendet wurden, dann in das Endprodukt übernommen, welches damit alleine (ohne die Bibliothek) lauffähig ist.

getrennte Uebersetzung [Datenflußplan]
        _____                    _____  
.-' '-. .-' '-. 
.' '. .' '. 
/ \ / \ 
; Uebersetzungs- ; ; Uebersetzungs- ; 
| Einheit | | Einheit | 
; 0 ; ; 1 ; 
\ / \ / 
'. .' '. .' 
'-._____.-' '-._____.-' 
| | 
V V 
.-------------------. .-------------------. 
| | | | 
| Uebersetzer | | Uebersetzer | 
| | | | 
'-------------------' '-------------------' 
| | 
__V__ __V__ _____ 
.-' '-. .-' '-. .-' '-. 
.' '. .' '. .' '. 
/ \ / \ / \ 
; Zwischen- ; ; Zwischen- ; ; Bibliothek ; 
| Produkt | | Produkt | | 0 | 
; 0 ; ; 1 ; ; ; 
\ / \ / \ / 
'. .' '. .' '. .' 
'-._____.-' '-._____.-' '-._____.-' 
| | | 
'---------------------. | .---------------------' 
| | | 
| | | 
V V V 
.-------------------. 
| | 
| Verbinder | 
| | 
'-------------------' 

__V__ 
.-' '-. 
.' '. 
/ \ 
; End- ; 
| Produkt | 
; ; 
\ / 
'. .' 
'-._____.-'

Nichtdefinierende Deklarationen

Wenn ein Übersetzer eine Übersetzungseinheit verarbeitet, die eine Entität verwendet, die in einer anderen Übersetzungseinheit definiert ist, dann kann der Übersetzer in vielen Fällen zunächst nichts über diese Entität wissen. Er verarbeitet die Übersetzungseinheit, in der die verwendete Entität definiert wird, ja nicht. Der Übersetzer kann dann nicht einmal prüfen, ob die Entität in der gerade übersetzten Einheit überhaupt richtig verwendet wird und kann auch nicht immer wissen, wie ein Bezug auf diese Entität richtig herzustellen ist.

Eine Entität, die in einer anderen Übersetzungseinheit definiert ist, als der gerade übersetzten, wird auch eine externe Entität  genannt. Eine Übersetzungseinheit mit Bezügen auf externe Entitäten einer anderen Übersetzungseinheit oder eines Zwischenproduktes oder einer Bibliothek, nennt man auch einen Klienten  dieser anderen Übersetzungseinheit, bzw. dieses Zwischenprodukts oder der Bibliothek. Man sagt, daß eine Übersetzungseinheit, ein Zwischenprodukt oder eine Bibliothek diejenigen Entitäten, auf welche sich andere Übersetzungseinheiten beziehen können, exportiert.

Damit der Übersetzer seine Arbeit erledigen kann, wird der Verwendung einer externen Entität oft eine nichtdefinierende Deklaration eines Bezeichners  vorangestellt. Solch eine Deklaration erfüllt zwei Aufgaben:

Anders als eine vollständige Definition wird durch eine nichtdefinierende Deklaration aber keine neue Entität angelegt.

Damit nicht jeder Klient immer wieder die nötigen nichtdefinierenden Deklarationen enthalten muß, wird zu einer Bibliothek oft eine für den Übersetzer verständlich Bibliotheksbeschreibung mitgeliefert, in der alle exportierten Entitäten nichtdefinierend Deklariert sind. So kann der Übersetzer alles nötige über Namen und Typ der exportierten Entitäten erfahren.

getrennte Uebersetzung mit Bibliotheksbeschreibung [Datenflußplan]
        _____                    _____  
.-' '-. .-' '-. 
.' '. .' '. 
/ \ / \ 
; Uebersetzungs- ; ; Bibliotheks- ; 
| Einheit | | beschreibung | 
; 0 ; ; 0 ; 
\ / \ / 
'. .' '. .' 
'-._____.-' '-._____.-' 
| | 
V | 
.-------------------. | 
| | | 
| Uebersetzer |<-------------' 
| | 
'-------------------' 

__V__ _____  
.-' '-. .-' '-. 
.' '. .' '. 
/ \ / \ 
; Zwischen- ; ; Bibliothek ; 
| Produkt | | 0 | 
; 0 ; ; ; 
\ / \ / 
'. .' '. .' 
'-._____.-' '-._____.-' 
| | 
'---------------------. | 
| | 
| | 
V V 
.-------------------. 
| | 
| Verbinder | 
| | 
'-------------------' 

__V__ 
.-' '-. 
.' '. 
/ \ 
; End- ; 
| Produkt | 
; ; 
\ / 
'. .' 
'-._____.-'

Bibliotheksdienste

Ein vollständiger, nützlicher Bibliotheksdienst besteht also aus zwei Teilen: Einer Beschreibung  der Bibliothek für den Übersetzer, in der Name und Typ der exportierten Entitäten deklariert wird und der eigentlichen Bibliothek  für den Verbinder, welche die nutzbaren Entität in bereits übersetzter Form enthält.

Anstelle eines Bibliotheksdienstes könnte der Dienst auch durch einen Quelltext bereitgestellt werden, der bei Bedarf jedesmal mit dem Klienten zusammen übersetzt wird. Die Verwendung eines Bibliotheksdienstes bietet demgegenüber jedoch den Vorteil, daß der Herstellungsprozeß schneller  durchlaufen werden kann, weil die Übersetzung der Bibliothek nicht mehr nötig ist, da diese schon in einer übersetzten Form vorliegt. Außerdem muß der Hersteller eines Bibliotheksdienst so den Quelltext  seiner Bibliothek nicht mit ausliefern und kann so sein geistiges Eigentum besser geheimhalten, falls dies gewünscht wird.

Ein Bibliotheksdienst
                   .--------------------------------. 
| | 
| Bibliotheksdienst 0 | 
| | 
| _____ | 
| .-' '-. | 
| .' '. | 
| / \ | 
| ; Bibliotheks- ; | 
| | beschreibung | | 
| ; 0 ; | 
| \ / | 
| '. .' | 
| '-._____.-' | 
| | 
| | 
| | 
| _____ | 
| .-' '-. | 
| .' '. | 
| / \ | 
| ; Bibliothek ; | 
| | 0 | | 
| ; ; | 
| \ / | 
| '. .' | 
| '-._____.-' | 
'--------------------------------'

Del.icio.us   |   Seiteninformationen und Impressum   |   Mitteilungsformular  |   "ram@zedat.fu-berlin.de" (ohne die Anführungszeichen) ist die Netzpostadresse von Stefan Ram.   |   Von der Stefan-Ram-Startseite ausgehend finden sich oft noch mehr Informationen zu Themen, die auf einer Seite angesprochen wurden. (Eine Verbindung zur Stefan-Ram-Startseite befindet sich ganz oben auf dieser Seite.)  |   Der Urheber dieses Textes ist Stefan Ram. Alle Rechte sind vorbehalten. Diese Seite ist eine Veröffentlichung von Stefan Ram. slrprd, PbclevtugFgrsnaEnz