Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Kurze Sicht in die Blackbox BDS - oder "Was geht ab... (https://www.delphipraxis.net/127445-kurze-sicht-die-blackbox-bds-oder-geht-ab.html)

heri 13. Jan 2009 13:57


Kurze Sicht in die Blackbox BDS - oder "Was geht ab...
 
Ich habe schon so einiges programmiert und ich denke auch einiges an Grundkenntnissen zu besitzen, möchte aber gerne "kurz" einmal die für die Programmierung wichtigen Zusammenhänge der Computerkomponenten notieren.

und es hat in diesem Forum bestimmt viele schlaue Köpfe sitzen, welche mir hierzu bei den Fragen und Ergänzungen zur Seite stehen, damit andere Einsteiger die Zusammenhänge einfacher und besser verstehen:

------------------------------------------------------------------------
Teil 1: Was geht ab... wenn ich ein Programm kompiliere? &
Teil 2: Was geht ab... wenn ich ein Programm starte?

------------------------------------------------------------------------
Teil 1: Was geht ab... wenn ich ein Programm kompiliere?
------------------------------------------------------------------------
Nun, die Voraussetzungen zum Kompilieren sind ("Man nehme..."):

Hardware:
- einen funktionierenden PC ;.)

------------------------------------------------------------------------
Software:
- Eine Entwicklungsumgebung zB die BDS!!! um Code zu verwalten:

- Sourcecode (händisch programmiert) wie im Beispielcode:
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
sValue1, sValue2: String;
iValue1, iValue2: Integer;
iSumValue: Integer;
begin

  sValue1 := Edit1.Text;
  sValue2 := Edit2.Text;

  iValue1 := StrToInt( sValue1 );
  iValue2 := StrToInt( sValue2 );

  iSumValue := iValue1 + iValue2;

  showmessage( inttostr( iSumValue ) );

end;
- und/oder von der Entwicklungsumgebung generiert zB: Unit1.dfm
(diese hat einfach zwei Edits und einen Button)

Delphi-Quellcode:
object Form1: TForm1
  Left = 0
  Top = 0
  Caption = 'Form1'
  ClientHeight = 133
  ClientWidth = 167
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  PixelsPerInch = 96
  TextHeight = 13
  object Button1: TButton
    Left = 40
    Top = 72
    Width = 75
    Height = 25
    Caption = 'Button1'
    TabOrder = 0
    OnClick = Button1Click
  end

  ....[gekürzt]....

end
- sowie CodeLibs der Entwicklungsumgebung wie die Units: Forms, SysUtils etc.
welche bei Bedarf (d.h. wenn in uses) Code dem Programm beisteuern.

------------------------------------------------------------------------
so weit so gut...

jetzt wird der Code kompiliert & gelinkt:

Ablauf:
1. ein Kompiler zB: dcc32.exe wandelt den Code in Maschinencode um

und
2. der Linker...
(hmmmmm, in wikipedia ist der Linker erklärt...aber ich verstehs in meinem Beispiel trotzdem nicht)

Wichtige Zusatzinfos:
Für die Parameterisierung des Kompilers im BDS: siehe Projektoptionen -> Compiler

------------------------------------------------------------------------
und fertig ist die ausführbare Datei!

war das wirklich schon das wichtigste in Kürze?


------------------------------------------------------------------------
Teil 2: Was geht ab... wenn ich ein Programm ausführe?
------------------------------------------------------------------------

das wird bestimmt etwas schwieriger...

Nun, die Voraussetzungen zum Ausführen einer ausführbaren Datei sind:

------------------------------------------------------------------------
Hardware:
- immer noch - ein funktionierender PC ;.)

------------------------------------------------------------------------
Software:
- Betriebssystem (OS) mit CodeLibs wie kernel.dll etc.


Ablauf:
1. Ich starte meine Datei

2. Das OS lädt die ganze Datei in den Arbeitsspeicher...
(Frage: hmm stimmt das? abgesehen von zusätzlich dynamisch geladenen DLL's)

3. Das Programm wird an einem fix definierten Ausführungspunkt ausgeführt
(siehe Project1.dpr -> begin)

4. Application.Initalize
-> Alle Units werden initalisiert
(Frage: Wenn eine Unit Code im initalization hat, ansonsten aber gar nicht benötigt wird, ist der Kompiler so schlau diese Unit zu ignorieren?)

5. Application.CreateForm(TForm1, Form1); -> Der für die Form nötige Speicher wird reserviert und
die Form1 wird created
(Frage: bedeutet "create" lediglich dass Speicher reserviert wird?)

6. Application.Run
-> Die Form1 wird angezeigt...
(Frage: einfach weils die erste erstellte Form ist? wie witzig...)
-> und aktiviert

Wichtige Zusatzinfos:
- zum Erstellen und Anzeigen von Komponenten werden Messages zwischen der Applikation und dem OS hin- und hergeschickt (zB: WM_Create etc.),
deshalb sieht eine Form jeweils passend zum ausgeführten OS aus
(Frage: welche CodeLib des OS ist hauptsächlich für das Erstellen der Form zuständig?)
- jede Komponente besitzt automatisch ein eindeutiges Handle
- ... [ bitte um Erweiterung... ]

Event: Der Button auf der Form wird gedrückt
10. Das OS erhält die Message WM_MouseClick und sendet diese an die Komponente weiter

11. Der Code vom Button1.OnClick (siehe Beispielcode oben) wird ausgeführt:

11.1 var... Es wird Arbeitsspeicher - an einer freien Stelle - für die Variablen reserviert
(Frage: Was ist der Stack...?)
11.2 Den Variablen wird ein Wert zugewiesen
11.3 iSumValue := iValue1 + iValue2;
-> In eine weitere Variable wird die Summe der beiden ersten Variablen zugewiesen
11.4 showmessage (aus der Unit Dialogs) sendet den Befehl weiter ans OS und zeigt das Ergebnis an

das wars - einfach gesagt? oder was gibts sonst noch wichtiges? hast du noch einen Input?


PS:
Vllcht weiss jemand ein gutes Buch welches diese Zusammenhänge gut erklären würde?

mkinzler 13. Jan 2009 14:21

Re: Kurze Sicht in die Blackbox BDS - oder "Was geht ab
 
Zitat:

(Frage: bedeutet "create" lediglich dass Speicher reserviert wird?)
Nein, es wird zusätzlich der Konstruktor aufgerufen.
Dieser erzeugt dann die Unterkomponenetn und lädt die Eistellungen des Formulars (dfm)
Zitat:

(Frage: einfach weils die erste erstellte Form ist? wie witzig...)
Weil es die Hauptform ist.
Zitat:

(Frage: welche CodeLib des OS ist hauptsächlich für das Erstellen der Form zuständig?)
Delphikomponenten basieren z.T. auf Windows-Controls (TWinControl) teils nicht.
Zitat:

(Frage: Was ist der Stack...?)
Ein bestimmter Bereich des Speichers indem im LIFO-Verfahren Werte abgelegt werden. Z.B. die Parameter für Funktionsaufrufe ( eigentlich ein Keller->Stapeln nach unten)

sirius 13. Jan 2009 15:54

Re: Kurze Sicht in die Blackbox BDS - oder "Was geht ab
 
Zitat:

Zitat von heri
Ich habe schon so einiges programmiert und ich denke auch einiges an Grundkenntnissen zu besitzen, möchte aber gerne "kurz" einmal die für die Programmierung wichtigen Zusammenhänge der Computerkomponenten notieren.

Oh, umd das sinnvoll zu ergänzen müsste man ein Buch schreiben.
Mal ein paar wichtige (was nicht heißt, dass ich zu den anderen nix zu sagen hätte)

Zitat:

Zitat von heri
2. der Linker...

Bastelt die deine einzelnen Units zu einer Exe zusammen und ergänz/korrigiert/etc. die Adressen der einzelnen Funktionen. Außerdem muss der Exe-Header geschrieben werden, naja, dass halt aus den einzelnen Codefetzen in den Units (kompiliert zu *.dcu) eine dem Betriebssystem genehme executable wird.

Zitat:

Zitat von heri
- Betriebssystem (OS) mit CodeLibs wie kernel.dll etc.

Ist eine CodeLib jetzt für dich eine Delphi-Unit oder die Bibliotheken des Betriebsystems?


Zitat:

Zitat von heri
2. Das OS lädt die ganze Datei in den Arbeitsspeicher...

Nicht zwingend alles auf einmal. Es gibt ja das Paging der Intel-Architektur. Dadurch hast du zwar alles in deinem virtuellen Speicher, aber unter Umständen kleben noch ein paar Seiten auf deiner Platte. Virtuell und damit für den Programmierer wichtig sieht es so aus, als wäre alles auf einmal im Speicher, mehr ist auch nicht wichtig.
Zitat:

Zitat von heri
4. Application.Initalize
-> Alle Units werden initalisiert

Nein.
das von dir genannte "begin" wird (in einer EXE) zum Aufruf des Befehls StartExe (Procedure in Unit System) umgebaut. Diese wiederum ruft u.a die Procedure initUnits auf. Und wie der Name schon sagt, wird da der Initialization-Teil der Units abgearbeitet.
Bspw. wird in der Unit Controls im Initialization-Teil die globale Variable Application (aus der Unit Forms) mit "Application:=TApplication.Create(..)" initialisiert. Damit ist das globale Objekt Application da.
Application.Initialize ist eine kleine Methode und macht nahezu nix.
Zitat:

Zitat von heri
(Frage: Wenn eine Unit Code im initalization hat, ansonsten aber gar nicht benötigt wird, ist der Kompiler so schlau diese Unit zu ignorieren?)

Nee, es kann ja auch sein, dass allein der Initialization-Teil wichtig für das Programm ist.

Zitat:

Zitat von heri
5. Application.CreateForm(TForm1, Form1); -> Der für die Form nötige Speicher wird reserviert und
die Form1 wird created

Man könnte das genauso auch mit Form1:=TForm1.Create(...) machen. Was anderes mach CreateForm auch nicht, außer das es sich die erste Form die kommt als MainForm nimmt.


Zitat:

Zitat von heri
6. Application.Run

Alle Messages von Windows werden in einer (Fast-)Endlosschleife abgearbeitet.

Zitat:

Zitat von heri
Event: Der Button auf der Form wird gedrückt
10. Das OS erhält die Message WM_MouseClick und sendet diese an die Komponente weiter

Das OS erhält einen Interrupt von der Mouse und generiert eine Mouse-Message an das Formular, mit dem Hinweis: Button X wurde angeklicckt. Die VCL generiert ihrerseits eine interne Message an den Button.


Zitat:

Zitat von heri
11.1 var... Es wird Arbeitsspeicher - an einer freien Stelle - für die Variablen reserviert

Der Stack ist großes Stück Speicher auf dem man sich "frei" austoben darf. Man sollte sich aber an gewisse Regeln halten und das macht Delphi auch. Prinzipiell wird für jede Funktion die aufgerufen wird ein Stackframe "angelegt". Das geht ganz einfach, man verschiebt einfach den StackPointer (ESP) nach unten und zwischen dem bisherigen Platz un dem neuen Platz von ESP kann man seine lokalen Variablen ablegen. Für Dynamische Variablen (Objekte, Strings, Arrays) muss noch außerhalb des Stacks (also auf dem Heap) Speicher reserviert werden. Das geschieht je nach Größe der Variablen und frei zur Laufzeit (deswegen ja dynamisch).


Edit: Falsche Tags

heri 13. Jan 2009 16:29

Re: Kurze Sicht in die Blackbox BDS - oder "Was geht ab
 
thx @mkinzler

Zitat:

(Frage: einfach weils die erste erstellte Form ist? wie witzig...)
Weil es die Hauptform ist.
Es gibt meines Wissens aber kein Propertie Form.MainForm := True
Deshalb denke ich, es ist die Hauptform, weils die erste erstelle ist?


thx @sirius
Zitat:

Oh, um das sinnvoll zu ergänzen müsste man ein Buch schreiben.
Ich suche ein Buch - hast du irgendwelche Tipps?

Zitat:

Betriebssystem (OS) mit CodeLibs wie kernel.dll etc.
Ist eine CodeLib jetzt für dich eine Delphi-Unit oder die Bibliotheken des Betriebsystems?
Ich kenne in BDS unter anderem folgende Dateien
- *.pas Pascal Code Dateien als Sourcecode vorhanden
- *.dcu Pascal Code Dateien aber bereits kompiliert
- *.dll als "fertige" Befehlsbibliotheken (welche natürlich auch vom OS zur Verfügung gestellt werden)

entsprechend konkretisierte Frage:
welche DLL des OS ist denn hauptsächlich für das Erstellen der Form zuständig?

mkinzler 13. Jan 2009 16:43

Re: Kurze Sicht in die Blackbox BDS - oder "Was geht ab
 
Zitat:

Es gibt meines Wissens aber kein Propertie Form.MainForm := True
Deshalb denke ich, es ist die Hauptform, weils die erste erstelle ist?
Ist keine Eigenschaft eines Formulars, sondern der Applikation. Das erste angelegte Formular wird automatisch zum Hauptformular. Man kann dies aber im Projekt einstellen.
Zitat:

welche DLL des OS ist denn hauptsächlich für das Erstellen der Form zuständig?
Keines, das macht die VCL

heri 13. Jan 2009 17:14

Re: Kurze Sicht in die Blackbox BDS - oder "Was geht ab
 
Zitat:

Es gibt meines Wissens aber kein Propertie Form.MainForm := True
Deshalb denke ich, es ist die Hauptform, weils die erste erstelle ist?

Ist keine Eigenschaft eines Formulars, sondern der Applikation. Das erste angelegte Formular wird automatisch zum Hauptformular. Man kann dies aber im Projekt einstellen.
ich Dödel :wall: klar doch..., selten gebraucht...

Zitat:

welche DLL des OS ist denn hauptsächlich für das Erstellen der Form zuständig?
Keines, das macht die VCL
ähm, aber reicht die VCL die Messages nicht ans OS und das OS zeichnet dann die Forms?
Für mich ist die VCL eh nur eine "Zwischenschicht" zwischen Applikation und dem OS?

heri 13. Jan 2009 17:29

Re: Kurze Sicht in die Blackbox BDS - oder "Was geht ab
 
Zitat:

Für Dynamische Variablen (Objekte, Strings, Arrays) muss noch außerhalb des Stacks (also auf dem Heap) Speicher reserviert werden. Das geschieht je nach Größe der Variablen und frei zur Laufzeit (deswegen ja dynamisch).
Delphi-Quellcode:
wenn ich folgendes programmiere:
var
i: Integer;
j: Int64;
c: Char;
s: String[10];
x: String;
begin
  i := 1;
  j := 2;
  c := '1';
  s := '0123456789';
  x := '01234567890123456789';
end;
wieviel Platz wird dann wann im Arbeitsspeicher reserviert?

ich behaupte:
zu Begin der Procedure:
i: 1 Byte
j: 2 Byte
c: 1 Byte
s: 1 Byte
x: 1 Byte

und zur Laufzeit wenn die Werte gesetzt werden:
i: 1 Byte
j: 2 Byte
c: 1 Byte
s: 10 Byte
x: 20 Byte

bitte um Korrektur

:duck: ich habe bis jetzt einfach immer nur programmiert, aber mir fehlen glaub noch ein paar Grundkenntnisse...

und bitte gleich noch um Ergänzung - falls dies jemand weiss:

auf einem SQL Server habe ich ein Feld varchar(255) mit dem Wert '0123456789' - wieviel Speicherplatz geht denn - bezogen auf dieses Feld - "verloren"
es sollten eigentlich ja 10 Byte sein - oder?

[edit=mkinzler]Delphi-Tags eingefügt Mfg, mkinzler[/edit]

cruiser 13. Jan 2009 18:07

Re: Kurze Sicht in die Blackbox BDS - oder "Was geht ab
 
zu Begin der Procedure:
i: 4 Byte // 32 Bit Wert = 4 Byte
j: 8 Byte // 64 Bit Wert = 8 Byte
c: 1 Byte // 8 Bit Wert = 1 Byte (wenn nicht Unicode)
s: 11 Byte // 1 Byte Längenangabe + 10 Byte Reserve
x: 4 Byte // ein 32bit Pointer auf einen Speicherbereich im Heap = 4 Byte


Dazu kommt dann noch der Overhead vom Speichermanager.

und zur Laufzeit wenn die Werte gesetzt werden:
i: 4 Byte
j: 8 Byte
c: 1 Byte
s: 11 Byte
x: 4 Byte Stack + 24 Byte Heap (4byte Längenangabe + 20 Byte String)


Edit: Man sollte nichts schreiben wenn man nicht auf der Höhe ist. Sorry :pale:

sirius 13. Jan 2009 18:08

Re: Kurze Sicht in die Blackbox BDS - oder "Was geht ab
 
Zitat:

Zitat von heri
Für Dynamische Variablen (Objekte, Strings, Arrays) muss noch außerhalb des Stacks (also auf dem Heap) Speicher reserviert werden. Das geschieht je nach Größe der Variablen und frei zur Laufzeit (deswegen ja dynamisch).

wenn ich folgendes programmiere:
Delphi-Quellcode:
var
i: Integer;
j: Int64;
c: Char;
s: String[10];
x: String;
begin
  i := 1;
  j := 2;
  c := '1';
  s := '0123456789';
  x := '01234567890123456789';
end;
wieviel Platz wird dann wann im Arbeitsspeicher reserviert?

Wir müssen unterscheiden: Stack und Heap.
Auf dem Heap muss man Speicher vor dem Gebrauch reservieren. Das geschieht bei
  • Objekten durch TKlasse.Create
  • durch new oder getmem
  • bei Strings implizit durch Zuweisung
  • bei Strings und dyn. Arrays explizit durch "Setlength"
  • (und eigentlich auch durch localalloc, globalalloc, oder virtualalloc) Aber den Punkt vergessen wir besser erstmal. Den brauch man in einer normalen Anwendung nicht
Auf dem Stack muss man nichts reservieren. Der Stack wird am Anfang (eines Threads) angelegt und ist je nach Einstellung so 100kB groß (siehe Objektoptionen) Und da kommen i.A. lokale Variablen, Übergabeparamter und Rücksprungadressen drauf.
Schau dazu mal in diese Präsentation: http://www.delphipraxis.net/internal...t.php?t=104196

Was macht deine Funktion? Sie schnappt sich auf dem Stack einfach 4 (Integer) + 8 (Int64) + 4 (Char; weniger als 4 geht nicht) + 12 (11 für shortstring mit Längenangabe und 1 für Alignment auf 4) + 4 (dynamischer String = Pointer) = 28 Bytes Und kann dort problemlos alle Werte reinschreiben. Außer beim dynamsichen String, da müsste die Funktion Speicher vom Heap reservieren (was die Länge + 1 Nullbyte + 8 "stringHeader" sind). Hier würde aber nur der 4 Byte große Pointer auf dem Stack zu dem Konstentenstring umgebogen, der im Image der Exe im speicher rumliegt. Das hängt mit Referenzzählung etc. zusammen. Du siehst, es ist alles komplizierter als so ein kurzer Beitrag erklären kann. Bücher kenne ich darüber nicht.

Zitat:

Zitat von heri
auf einem SQL Server habe ich ein Feld varchar(255) mit dem Wert '0123456789' - wieviel Speicherplatz geht denn - bezogen auf dieses Feld - "verloren"
es sollten eigentlich ja 10 Byte sein - oder?

Hmm, eigentlich nur eine Frage pro Thread. Sonst sihet man hier nicht mehr durch. Das oben ist ja vielleicht noch ok (muss zum Glück ein Mod entscheiden, nicht ich). Aber jetzt schweifst du komplett zu Datenbanken ab. Frag doch einfach mal in einem neuen Thread (ich würde übrigens sagen 10Byte - wegen varchar.



Zitat:

Zitat von heri
welche DLL des OS ist denn hauptsächlich für das Erstellen der Form zuständig?
Zitat:

Zitat von mkinzler
Keines, das macht die VCL

ähm, aber reicht die VCL die Messages nicht ans OS und das OS zeichnet dann die Forms?
Für mich ist die VCL eh nur eine "Zwischenschicht" zwischen Applikation und dem OS?

Ja @heri, die VCL ist zum einen "nur" eine Kapselung der WinAPI zum anderen aber auch mit nützlichen Erweiterung. Bei einer Form oder einem Button (also diese Standard-Kompos) trifft "einfach" in etwa zu. Die DLL von Windows ist dann die user32.dll (oder user32.lib) Hilft dir aber bei der Anwendung von Delphi nicht wirklich weiter. Da ist die VCL für dich der Ansprechpartner. (was wahrscheinlich mkinzler in seiner üblichen kurzen Form ausdrücken wollte).

mr_emre_d 13. Jan 2009 19:58

Re: Kurze Sicht in die Blackbox BDS - oder "Was geht ab
 
o Byte = (signed) 1 Byte 0..255 2^8
o Word = (signed) 2 Bytes 0..65535 2^16
o Cardinal = (signed) 4 Bytes 0..4294967295 2^32
o LongWord = Cardinal

o ShortInt = (unsigned) 1 Byte -128..127 2^8
o SmallInt = (unsigned) 2 Bytes -32768..32767 2^16
o Integer = (unsigned) 4 Bytes -2147483648..2147483647 2^32
o Int64 = (unsigned) 8 Bytes -2^64..2^64-1

Also mehr fällt mir gerade nicht ein .. das sind so die gängisten typen ..
Es gäbe noch Float-Typen .. Single & Double = 4 Byte ...

--EDIT
Was Strings angeht:
Strings sind nur aneinander gereihte Chars, die jeweils (signed) 1 Byte groß sind
(eigentlich nicht ganz .. siehe dazu http://www.manuel-poeter.de/hitcounte ... le&file=tutorials/Strings.zip) Wink
--EDIT END

Das müsste allerdings für den Anfang reichen.

Falls du mehr wissen willst, wie Echsen innerlich ausschauen/funktionieren, empfehle ich dir:

http://www.microsoft.com/downloads/de ... 8-D89FFE4F2B46&displaylang=en


Alle Zeitangaben in WEZ +1. Es ist jetzt 00:39 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz