Rheinwerk Computing < openbook > Rheinwerk Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger.

Inhaltsverzeichnis
Geleitwort
Vorwort
1 PEAR – Einführung
2 Authentication
3 Caching
4 Date and Time
5 File Formats
6 HTTP
7 Internationalization
8 Mail
9 Networking
10 PHP
11 Text
12 Web Services
13 Benchmarking
14 Configuration
15 Database
16 File System
17 HTML
18 Images
19 Logging
20 Math
21 Numbers
22 Tools and Utilities
23 XML
24 Selbst Pakete erstellen
25 PECL
Index
Ihre Meinung?

Spacer
 <<   zurück
PHP PEAR von Carsten Möhrke
Anwendung und Entwicklung – Erweiterungen für PHP schreiben
Buch: PHP PEAR

PHP PEAR
798 S., 39,90 Euro
Rheinwerk Computing
ISBN 3-89842-580-0
gp 25 PECL
  gp 25.1 Allgemeines
  gp 25.2 Installation
  gp 25.3 crack
  gp 25.4 apd
  gp 25.5 bcompiler
  gp 25.6 perl
  gp 25.7 Xdebug
  gp 25.8 APC
  gp 25.9 IDN
  gp 25.10 blenc
  gp 25.11 xmlreader
  gp 25.12 xmlwriter
  gp 25.13 id3


Rheinwerk Computing

25.7 Xdebug  toptop


Version: 2.0.0beta2 Lizenz: BSD-Lizenz

Bei Xdebug handelt es sich um einen weiteren Debugger. Im Gegensatz zu apd liegt der Schwerpunkt in diesem Fall aber mehr auf dem Debugging und nicht so sehr auf dem Profiling. Nichtsdestotrotz wird auch in diesem Paket ein hochwertiges Profiling unterstützt.

Xdebug geht ein wenig mehr unter die Oberfläche, als apd das tut, und arbeitet somit näher am System. Diese fortschrittliche Technik in Kombination mit einem Protokoll namens GDB ermöglicht es, den Debug-Vorgang von außen zu steuern. Das heißt, Sie können mithilfe von Programmen wie der Maguma Workbench die Ausführung des Codes anhalten, um genauer zu untersuchen, was gerade passiert.

Xdebug greift sofort in Ihr System ein. Das heißt, selbst dann, wenn Sie keine entsprechenden Funktionen aufrufen, verhält sich Ihr System zum Beispiel bei der Fehlerbehandlung anders.Nachdem Sie Xdebug geladen haben, könnte eine Fehlermeldung beispielsweise so aussehen wie in Abbildung 25.1.

Abbildung 25.1 Fehlermeldung mit Xdbug

Solche Fehlermeldungen können durchaus auch deutlich umfangreicher werden, da hier der komplette Call-Stack eingeblendet wird. Auf dem Call-Stack werden alle Funktionsaufrufe der Reihe nach abgelegt.

Möchten Sie dieses Verhalten unterdrücken, können Sie Xdebug mithilfe der Funktion xdebug_disable() ausschalten. Möchten Sie die Funktionalitäten wieder einschalten, steht xdebug_enable() zur Verfügung. Um den aktuellen Status zu prüfen, können Sie xdebug_is_enabled() aufrufen. Diese Funktion gibt true zurück, wenn das System aktiviert ist, und sonst ein false.

Die anderen Funktionen, die das System bietet, sind jeweils zu Gruppen zusammengefasst, um eine möglichst gute Strukturierung zu ermöglichen. Jede dieser Befehlsgruppen deckt einen bestimmten Leistungsumfang ab.

Die erste Gruppe sind die Code-Coverage-Funktionen. Diese bieten Ihnen die interessante Möglichkeit herauszufinden, welche Zeilen Ihres Codes ausgeführt wurden.

Um eine Code-Coverage-Analyse durchzuführen, müssen Sie zuerst die Funktion xdebug_start_code_coverage() aufrufen. Nachdem der Code ausgeführt worden ist, können Sie mit xdebug_get_code_coverage() und xde bug_get_function_count() Informationen über die ausgeführten Zeilen auslesen. In Listing 25.9 finden Sie ein Beispiel für die Nutzung.

<?php 
xdebug_start_code_coverage(); 
 
$i = 0; 
while ($i < 10) 
{ 
   echo $i; 
   $i++; 
} 
 
var_dump(xdebug_get_code_coverage()); 
var_dump(xdebug_get_function_count()); 
 
xdebug_stop_code_coverage();‚ 
?>

Listing 25.9 Code-Coverage-Analyse mit Xdebug

Wie Sie in Listing 25.9 sehen, wird, nachdem die beiden Xdebug-Funktionen aufgerufen wurden, noch die Funktion xdebug_stop_code_coverage() ausgeführt, die den Vorgang beendet und alle Ressourcen wieder freigibt. Die Ausgabe der beiden Xdebug-Funktionen sieht wie folgt aus:

array 
  '/home/netviser/xdb.php' => 
    array 
      4 => 1 
      5 => 1 
      7 => 1 
      8 => 1 
      9 => 1 
      11 => 1 
 
4

Wie Sie sehen, liefert xdebug_get_code_coverage() ein Array zurück. In der ersten Dimension ist der Name der Datei, die ausgeführt wird, der Schlüssel. Danach folgt ein weiteres Array, bei dem die Schlüssel den Nummern der Zeilen entsprechen, die ausgeführt wurden. Der Wert ist immer 1. In Version 1 zählte Xdebug noch, wie oft eine Zeile aufgerufen wurde. Inzwischen wird aber nur noch dokumentiert, ob eine Zeile überhaupt ausgeführt wurde. Die Methode gibt nur die Zeilennummern zurück, die für die Ausführung von Bedeutung sind. Leerzeilen sowie Zeilen, die nur eine öffnende Klammer enthalten, werden ignoriert.

Die 4 am Ende der Ausgabe ist der Rückgabewert der Funktion xdebug_get_function_count(). Hierbei handelt es sich um die Anzahl der Funktionsaufrufe während der Programmausführung. Vier Aufrufe resultieren aus den beiden Aufrufen von var_dump() und den Aufrufen von xdebug_get_code_coverage() und xdebug_get_function_count(). Das echo, das ja auch ausgeführt wird, taucht in der Zählung nicht auf, da es sich hierbei nicht um eine Funktion, sondern um ein Sprachkonstrukt handelt.

Die nächste Gruppe von Funktionen sind die »Execution Related Functions«. Da sich im Endeffekt alle Funktionen auf die Ausführung des Codes beziehen, finde ich die Namensgebung nicht ganz geschickt. Hierbei handelt es sich um Funktionen, die Ihnen mitteilen, wie viel Arbeitsspeicher Ihr Script während der Ausführung benötigt und welche Funktionen aufgerufen werden. Interessant ist hierbei, dass die Informationen zu den Funktionsaufrufen in eine Datei geschrieben werden, um die Informationen zur Speichernutzung nicht zu verfälschen.

Die Funktion xdebug_start_trace(), die den Tracing-Vorgang einleitet, bekommt den Namen der Datei übergeben, in der die Daten abgelegt werden sollen. Wie viel Arbeitsspeicher Ihr Skript aktuell benötigt, können Sie mit der Funktion xdebug_memory_usage() auslesen. xdebug_peak_memory_usage() liefert Ihnen die Größe des Bereichs im Arbeitsspeicher zurück, der während der Ausführung maximal benötigt wurde.

Um die Laufzeit des Codes besser untersuchen zu können, nutzen Sie am besten die Funktion xdebug_time_index(). Diese liefert Ihnen den aktuellen Zeitindex als Fließkommazahl zurück. Ein Beispiel für die Nutzung der Funktionen finden Sie in Listing 25.10.

function foo() 
{ 
   $i=100000; 
   while ($i--) $e=sqrt($i); 
} 
 
function bar () 
{ 
   for ($j=0; $j<3; $j++) 
   { 
      foo(); 
   } 
} 
 
 
$file = 'TRACEFILE'; 
xdebug_start_trace($file); 
 
$time_before=xdebug_time_index(); 
$mem_before=xdebug_memory_usage(); 
 
bar(); 
 
$mem_after=xdebug_memory_usage(); 
$time_after=xdebug_time_index(); 
 
echo "Laufzeit: ".($time_after-$time_before); 
echo "<br />Speicher vorher: $mem_before"; 
echo "<br />Speicher nachher: $mem_after"; 
echo "<br />Speicher maximal: ".xdebug_peak_memory_usage(); 
 
xdebug_stop_trace();

Listing 25.10 Profiling mit Xdebug

Wundern Sie sich nicht über die beiden Funktionen, die aufgerufen werden. Sie sollen nur als Beispiel dienen, und foo() soll die Laufzeit nach oben treiben.

Das Skript erzeugt eine Ausgabe wie diese:

Laufzeit: 9.02735699993 
Speicher vorher: 47760 
Speicher nachher: 47992 
Speicher maximal: 70384

Wie ich aber schon erwähnt habe, erzeugt das System automatisch eine Datei mit Informationen. In diesem Fall wird sie unter dem Namen TRACEFILE.xt abgelegt. Der Dateiname wird also mindestens um das Suffix .xt ergänzt.

In der Datei finden Sie Daten wie diese:

TRACE START [2005–04–15 22:39:50] 
0.0486  47760  -> xdebug_time_index() /home/xdb.php:21 
0.0487  47760  -> xdebug_memory_usage() /home/xdb.php:22 
0.0488  47760  -> bar() /home/xdb.php:24 
0.0489  47848    -> foo() /home/xdb.php:13 
0.0490  47920      -> sqrt() /home/xdb.php:6 
0.0491  47976      -> sqrt() /home/xdb.php:6 
// Stark gekuerzt 
9.0758  47992      -> sqrt() /home/xdb.php:6 
9.0760  47992  -> xdebug_memory_usage() /home/xdb.php:26 
9.0760  48040  -> xdebug_time_index() /home/xdb.php:27 
9.0763  48192  -> xdebug_peak_memory_usage() /home/ xdb.php:32 
9.0764  48192  -> xdebug_stop_trace() /home/ xdb.php:34 
TRACE END   [2005–04–15 22:39:59]

Jeder Funktionsaufruf, den das Script tätigt, wird in dieser Datei dokumentiert. Aufgrund der großen Anzahl von Aufrufen der Funktion sqrt() habe ich die Datei hier deutlich gekürzt.

In jeder Zeile finden Sie den Zeitindex, zu dem die Funktion aufgerufen wurde, worauf der belegte Speicher folgt. Nach einem Minus und einem Größer-als folgt der Name der Funktion, die aufgerufen wird. Wie Sie in diesem Beispiel gut sehen können, wird eine Funktion, die durch eine andere aufgerufen wird, jeweils weiter eingerückt. Die Zeile wird mit dem Dateinamen und der Zeilennummer beendet, in der der Funktionsaufruf stattfindet.

Eine solche Datei kann schnell mithilfe eines Scripts aufbereitet werden, so dass Sie sich nicht durch ellenlange Datenreihen quälen müssen.

Hilfreich sind auch die beiden Funktionen zum »Dumpen« von Variableninhalten. Aus PHP werden Sie sicher die Funktion var_dump() kennen, die den kompletten Inhalt einer Variablen und ihren Datentyp ausgibt. In Xdebug ist diese äquivalent als xdebug_var_dump() formuliert. Der Vorteil der Xdebug-Variante besteht darin, dass die Daten so ausgegeben werden, dass sie im Browser formatiert dargestellt werden.

Zusätzlich ist in Xdebug noch xdebug_dump_superglobals() definiert. Mit dieser Funktion können Sie den Inhalt und den Datentyp von superglobalen Array-Elementen ausgeben lassen. Die Funktion bekommt das superglobale Array, also z. B. $_POST, $_GET oder eines der anderen, übergeben. Allerdings wird nicht automatisch der gesamte Inhalt ausgegeben. Sie müssen festlegen, welche der Inhalte Sie benötigen. Leider können diese Informationen nicht direkt an die Funktion übergeben werden. Es ist erforderlich, dass diese mit der Konfigurationsdirektive xdebug.dump festgelegt werden. Die Xdebug-Anleitung schlägt an dieser Stelle vor, die Einstellung über die php.ini vorzunehmen, was mir allerdings ein wenig umständlich erscheint. Daher nutze ich üblicherweise ini_set(). Folgendes Beispiel verdeutlicht die Nutzung:

session_start(); 
 
ini_set('xdebug.dump.GET','vorname,nachname'); 
ini_set('xdebug.dump.SESSION','id'); 
 
xdebug_dump_superglobals($_GET); 
xdebug_dump_superglobals($_SESSION);

An die Direktive xdebug.dump wird also jeweils der Name des superglobalen Arrays angehängt, das ausgegeben werden soll. Die Namen der Schlüssel, die ausgegeben werden sollen, weisen Sie der Direktive zu. Alle Schlüssel müssen als ein String zusammengefasst und übergeben werden. Wichtig ist, dass der String keine Leerzeichen enthält.

Sobald Sie jetzt die Funktion xdebug_dump_superglobals() aufrufen und ihr den Namen des fraglichen Arrays übergeben, werden die entsprechenden Daten ausgegeben, wie Sie in Abbildung 25.2 sehen können.

Abbildung 25.2 Ausgabe der Superglobals

Die Daten, die über die URL übergeben wurden, werden entsprechend ausgegeben. Die Session-Variable hingegen existiert nicht und taucht somit auch nicht in der Tabelle auf. Existiert ein Schlüssel nicht, wird weder eine Fehlermeldung generiert noch weist das Programm Sie darauf hin.

Die letzte Gruppe von Befehlen sind die Befehle, mit denen Sie den Call-Stack untersuchen können. Wie schon erwähnt, werden hier die aktuellen Funktionsaufrufe auf einem Stapel abgelegt. Zwar können Sie diese Daten auch mithilfe eines Tracefiles ermitteln, aber es kann deutlich einfacher sein, eine der »Stack Related Funktions« zu nutzen. Wird eine Funktion von einem Objekt aufgerufen, gibt xdebug_call_class() Ihnen den Namen der dazugehörigen Klasse zurück. xdebug_call_function() leistet das Gleiche für eine Funktion, von der eine andere Funktion aufgerufen wurde, und xdebug_call_line() sagt Ihnen, aus welcher Zeile ein Aufruf erfolgte. Sollte Sie interessieren, in welcher Datei der Aufruf zu finden ist, kann xdebug_call_file() Ihnen das mitteilen.

Um den ganzen Stack auszuwerten, können Sie mit xdebug_get_stack_depth() die aktuelle Tiefe bzw. Höhe des Stapels in Erfahrung bringen. Den kompletten Inhalt des Stacks stellt die Funktion xdebug_get_function_stack() Ihnen in Form eines Arrays zur Verfügung.

Listing 25.11 verdeutlicht die Nutzung der Funktionen.

<html> 
<?php 
function foo() 
{ 
   echo "Aufruf aus Datei: ".xdebug_call_file(); 
   echo "<br />Aufruf von Funktion: ".xdebug_call_function(); 
   echo "<br />Aufruf aus Zeile: ".xdebug_call_line();_$ret_
   echo "<br />Tiefe des Stacks: ".xdebug_get_stack_depth(); 
   echo "<br />Inhalt des Stacks:"; 
   xdebug_var_dump(xdebug_get_function_stack()); 
} 
 
function bar () 
{ 
   foo(); 
} 
 
bar(); 
?> 
</html>

Listing 25.11 Analyse des Stacks mit Xdebug

Listing 25.11 erzeugt die folgende Ausgabe:

Aufruf aus Datei: /home/xdb.php 
Aufruf von Funktion: bar 
Aufruf aus Zeile: 15 
Tiefe des Stacks: 3 
Inhalt des Stacks: 
 
array 
  0 => 
    array 
      'function' => '{main}' 
      'file' => '/home/xdb.php' 
      'line' => 0 
      'params' => 
        array 
          empty 
  1 => 
    array 
      'function' => 'bar' 
      'file' => '/home/xdb.php' 
      'line' => 18 
      'params' => 
        array 
          empty 
  2 => 
    array 
      'function' => 'foo' 
      'file' => '/home/xdb.php' 
      'line' => 15 
      'params' => 
        array 
          empty

Vielleicht haben Sie sich schon gewundert, dass ich in Listing 25.11 den Quelltext mit <html> einleite. Das soll nur verdeutlichen, dass die Ausgabe der Zeilennummer sich immer auf die Zeile in der Datei bezieht und nicht auf den reinen PHP-Code.

Die Ausgabe des Stacks ist weitgehend selbsterklärend. Die erste Funktion hat den Namen {main}. Hierbei handelt es sich um das eigentliche »Hauptprogramm«. Aus diesem heraus wird die Funktion bar() aufgerufen, die ihrerseits die Funktion foo() aufruft.

Für jede Funktion ist noch ein zusätzliches Array vorgesehen, das die Parameter enthält, die an die Funktion übergeben wurden. In der aktuellen Version scheint hier allerdings noch ein Bug enthalten zu sein, da das Array immer leer bleibt.

Die letzte und vielleicht interessanteste Funktion ist die Nutzung eines externen Debuggers. Xdebug gibt Ihnen hiermit die Möglichkeit, die Ausführung des Codes anzuhalten. Hierzu gibt es zwei Möglichkeiten. Zum Ersten können Sie den Debug-Client nutzen, den Xdebug selbst zur Verfügung stellt. Für Linux und Windows können Sie diesen in fertig kompilierter Form unter http://www.xdebug.org herunterladen. Des Weiteren können Sie hier auch den C-Sourcecode finden, falls Sie den Client auf einer anderen Plattform nutzen wollen. Wenn Sie den Client herunterladen, beachten Sie bitte, dass es zwei Versionen gibt: eine für das GDB- und eine für das DBGp-Protokoll. Xdebug nutzt ab der Version 2 standardmäßig das DBGp-Protokoll.

Um einen externen Debugger nutzen zu können, müssen Sie zunächst die Datei php.ini um die Direktive xdebug.remote_enable=On ergänzen. Um die PHP-Datei über einen externen Debugger steuern zu können, müssen Sie die URL um DEBUG_SESSION_START=name ergänzen, wobei Sie name bitte durch einen individuellen Namen ersetzen.

Im Quelltest der zu testenden Anwendung können Sie die Funktion xdebug_break() nutzen, um die Ausführung des Codes anzuhalten. Sie fungiert als Haltepunkt.

Um eine Debug-Session zu starten, rufen Sie zuerst den Client auf. Dieser startet und wartet darauf, dass sich der Debug-Server mit ihm verbindet. Dies geschieht dann, wenn Sie die Anwendung im Browser beispielsweise mit http://www.example.org/file.php?XDEBUG_SESSION_START=sess1 aufrufen.

Für das folgende Beispiel wurde dieser Code genutzt:

<?php 
function ausgabe ($val) 
{ 
   echo "$val "; 
   xdebug_break(); 
} 
 
for ($cnt=0; $cnt < 5; $cnt +=1) 
{ 
   ausgabe($cnt); 
} 
?>

Listing 25.12 Code zum Debuggen

Einen Ausschnitt aus der Debug-Sitzung sehen Sie in Abbildung 25.3.

Abbildung 25.3 Ausschnitt aus der Debug-Sitzung

Nachdem die PHP-Seite aufgerufen wurde, verbindet sich der Server mit dem Client, was dieser durch die Ausgabe einer solchen Meldung bestätigt:

<init fileuri="file:///home/netviser/public_html/xdb.php" 
language="PHP" protocol_version="1.0" appid="18918" idekey="sess1"> 
   <engine version="2.0.0beta2"> 
      <![CDATA[Xdebug]]> 
   </engine> 
   <author> 
      <![CDATA[Derick Rethans]]> 
   </author> 
   <url> 
      <![CDATA[http://xdebug.org]]> 
   </url> 
   <copyright> 
      <![CDATA[Copyright (c) 2002–2004 by Derick Rethans]]> 
   </copyright> 
</init>

Der Server sendet seine Ausgaben immer als XML-Daten an den Client. Das ist leider ein wenig gewöhnungsbedürftig. Dass die Daten als XML geliefert werden, liegt daran, dass Sie hier den nativen Rückgabewert des Servers sehen. Da die Protokolle nicht primär für ein manuelles Debugging gedacht sind, wurde diese Vorgehensweise gewählt.

Im Tag <init> finden Sie das Attribut appid, das eine eindeutige ID enthält, die für die Debug-Sitzung benötigt wird.

Nachdem die Verbindung zum Debug-Client hergestellt worden ist, müssen Sie dort einmal den Befehl run eingeben, um die Applikation zu starten. run bekommt, wie alle anderen Befehle auch, die ID der Applikation mithilfe der Option -i übergeben. Mithilfe der ID wird spezifiziert, welcher der Prozesse weiter fortgeführt werden soll.

Nach dem run-Befehl stoppt die Applikation, wenn sie in der Funktion auf den Haltepunkt, also die Funktion xdebug_break(), trifft.

Um zu erfahren, welche Informationen in diesem Fall auf dem Call-Stack abgelegt sind, nutzen Sie zum Beispiel folgenden Befehl:

context_get -i 18917 -d 1

context_get gibt Ihnen in diesem Fall den Stack-Kontext der Tiefe 1 (-d 1) der Applikation mit der ID 18917 zurück. In diesem Beispiel wurde eine Funktion aufgerufen, so dass der Kontext sich in der Tiefe 1 des Stacks befindet. Befänden sich mehr Funktionen auf dem Stack, könnten Sie mit -d natürlich auch eine andere Tiefe spezifizieren. Auch in diesem Fall handelt es sich um eine XML-Nachricht, die zurückgegeben wird:

<response command="context_get" transaction_id="18917"> 
   <property name="val" fullname="$val" address="136395852"  
   type="int"> 
      <![CDATA[0]]> 
   </property> 
</response>

Für jede Variable bekommen Sie also die Information, welchen Namen sie hat (fullname), welchen Datentyp sie hat (type) und welchen Wert sie enthält (Inhalt der CDATA-Section).

Wichtig bei einem Zugriff auf den Stack ist, dass Sie nicht vergessen, dass es sich um einen Stapel handelt. Das heißt, die Tiefe 1 bezeichnet das oberste Element, also die Funktion, die zuletzt aufgerufen wurde. Mit Angabe der Tiefe 2 würden Sie den Kontext von {main}, sprich den Kontext des Hauptprogramms, auslesen.

Möchten Sie in Erfahrung bringen, welche Funktion sich an welcher Stelle des Stacks befindet, hilft stack_get Ihnen weiter. Auch hier werden wieder mithilfe von -i und -d die ID und die Tiefe spezifiziert. In der Rückgabenachricht sind dann der Name der Funktion sowie die Nummer der Zeile, aktuell in der Funktion ausgeführt wird. Wie viele Elemente sich gerade auf dem Stack befinden, können Sie mit stack_get auslesen. Dieser Befehl benötigt nur die ID der Applikation.

Möchten Sie die Sitzung beenden, geben Sie quit ein.

Das ist nur ein kleiner Ausschnitt aus dem Spektrum der Möglichkeiten. So ist es durchaus möglich, einzelne Variablen auszulesen, Variablen Werte zuzuweisen oder auch die Haltepunkte zu manipulieren. Da ich Ihnen allerdings ein Programm wie die Maguma Workbench empfehlen würde, um mit diesem Debugger zu arbeiten, möchte ich nicht auf alle Befehle eingehen. Eine komplette Liste der Befehle finden Sie unter der URL http://xdebug.org/docs-dbgp.php.

 <<   zurück
     
  Zum Rheinwerk-Shop
Zum Rheinwerk-Shop: PHP PEAR
PHP PEAR
Jetzt Buch bestellen!
 Ihre Meinung?
Wie hat Ihnen das Openbook gefallen?
Ihre Meinung

 Buchtipps
Zum Rheinwerk-Shop: PHP 5.6 und MySQL 5.7






 PHP 5.6 und
 MySQL 5.7


Zum Rheinwerk-Shop: Einstieg in PHP 5.6 und MySQL 5.6






 Einstieg in PHP 5.6
 und MySQL 5.6


Zum Rheinwerk-Shop: Responsive Webdesign






 Responsive Webdesign


Zum Rheinwerk-Shop: Moderne Websites entwickeln






 Moderne Websites
 entwickeln


Zum Rheinwerk-Shop: MySQL 5.6






 MySQL 5.6


 Lieferung
Versandkostenfrei bestellen in Deutschland, Österreich und der Schweiz
InfoInfo








Copyright © Rheinwerk Verlag GmbH 2007
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das Openbook denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt.
Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


Nutzungsbestimmungen | Datenschutz | Impressum

Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, service@rheinwerk-verlag.de

Cookie-Einstellungen ändern