Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Maximale Arraylänge? (https://www.delphipraxis.net/154805-maximale-arraylaenge.html)

Delphi-Narr 26. Sep 2010 11:40

Delphi-Version: 5

Maximale Arraylänge?
 
Hallo, ich habe mir eine eigene Komponente erstellt: Einen Graphen. Man kann zwischen runder Kurve und Punktgenauen Linien unterscheiden. Als Quelle für die Punkte gibt es einen Klasse:


Delphi-Quellcode:
TValues=array of real;

private
    XV:TValues;
    YV:TValues;


Wenn ich jetzt die Y-Werte auffülle (Also erst die Länge der Arrays festlege und dann die Werte eintrage) und das ganze auch mit den X-Werten mache, habe ich schonmal meine Wertetabelle. Das Ganze wird auch ordnungsgemäß aufgezeichnet.
Doch ab einer bestimmten Arraylänge klappt das nicht mehr.
Wenn ich jeweils (Für XV und YV) jeweils von 0 bis 198 eintrage (also 199 Werte) klappt es. Doch bei 200 nicht mehr. Warum???

Viele Grüße!

Luckie 26. Sep 2010 11:44

AW: Maximale Arraylänge?
 
Was heißt "klappt nicht mehr"? Fehlermeldung? Programmabsturz? Und wie sieht dein Code aus? Die Arraygröße ist nur durch den Datentyp des Indexes und dem größten freien Speicherbereich begrenzt.

mkinzler 26. Sep 2010 11:45

AW: Maximale Arraylänge?
 
Die Grenze sollten die Größe des größten Verfügbaren Speicherbereichs sein.
Warum speicherst du X und Y Werte getrennt man könnte dafür ja auch einen Record deklarieren.

Btw.:
Warum weigerst du es, Tags für deinen Quellcode zu verwenden?

Delphi-Narr 26. Sep 2010 11:52

AW: Maximale Arraylänge?
 
Es kommt weder Fehlermeldung noch Absturz. Der Graph wird einfach nicht mehr gezeichnet. Nur die Achsen sind noch sichtbar...

Hier der Aufruf, um zu malen

Delphi-Quellcode:
var i:integer;
begin
     randomize;
     for i:=0 to 198 do
     begin
     G1.XValues[i]:=-400+4*i;
     G1.YValues[i]:=Random(599)-300;
     end;
     G1.Redraw;
end;
Es werden die Werte 0 bis 198 zufällig eingetragen (zumindest y) und der Graph wird neu gezeichnet. Dieser aufruf klappt, dich wenn man die 198 durch 199 ersetzt, klappt es nicht mehr... Arraylänge wird vorher angepasst.


Hier die Prozedur "Redraw" Sorry für formatierung, ist nur kopiert...

Delphi-Quellcode:
procedure TLbGraph.Redraw(Delete:Boolean=True);
var i,l,X,Y,dX,dY:integer;
    Ps:Array of TPoint;
    Pt:TPoint;
    XA,YA:Boolean;  //Achsen zeichnen???
begin
     SetLength(Ps,0);
     if (Length(XV)=0) or (Length(YV)=0) then exit;

     if Length(XV)>Length(YV) then l:=Length(YV) else l:=Length(XV); //den kürzeren Array nehmen



     
     SetLength(PS,l);

     for i:=0 to l-1 do
     begin
          PS[i]:=XYtoPixels(XV[i],YV[i]);
     end;

     
     if Delete then G.canvas.FillRect(Rect(0,0,width,height));


     XA:=False;
     YA:=False;

     Pt:=XYToPixels(0,0);
     if (PT.x>30) and (Pt.x<width-30) then
     begin
          x:=Pt.x;
          YA:=True;
     end
     else
     x:=10;

     if (PT.y>30) and (Pt.y<height-30) then
     begin
          y:=Pt.y;
          XA:=True;
     end
     else y:=height-30;

     if XA then
     begin
          G.canvas.pen.color:=clblack;
          //XAchse malen
          G.canvas.MoveTo(-1,Y);
          G.canvas.LineTo(width+1,y);

          i:=10;
          while i<width-40 do
                begin
                     G.canvas.Font.size:=5;
                     if (i<x-20) or (i>x+20) then G.canvas.TextOut(i,Y-10,FloatToStrf(PixelsToXY(i,i).x,fffixed,10,2));
                     i:=i+50;
                end;
     end;

     if YA then
     begin
          G.canvas.pen.color:=clblack;
          //YAchse malen
          G.canvas.MoveTo(X,-1);
          G.canvas.LineTo(X,height+1);
          i:=10;
          while i<height-40 do
                begin

                     G.canvas.Font.size:=5;
                     if (i<y-20) or (i>y+20) then G.canvas.TextOut(X+10,i,FloatToStrf(PixelsToXY(i,i).y,fffixed,10,2));
                     i:=i+50;
                end;
     end;

     G.Canvas.pen.color:=clgray;

     if not XA then
     begin
          i:=10;
          while i<width-40 do
                begin
                     G.canvas.Font.size:=5;
                     if (i<x-20) or (i>x+20) then G.canvas.TextOut(i,y,FloatToStrf(PixelsToXY(i,i).x,fffixed,10,2));
                     i:=i+50;
                end;
     end;

     if not YA then
     begin
          i:=10;
          while i<height-40 do
                begin
                     G.canvas.Font.size:=5;
                     if (i<y-20) or (i>y+20) then G.canvas.TextOut(x,i,FloatToStrf(PixelsToXY(i,i).y,fffixed,10,2));
                     i:=i+50;
                end;
     end;

     //Graphen zeichnen
     if GraphKind=gkstraight then
     begin
          G.canvas.pen.color:=clred;
          G.canvas.Polyline(Ps);
     end
     else

     if GraphKind=gkrounded then
     begin
          G.canvas.pen.color:=clred;
          G.canvas.Polybezier(Ps);
     end;
end;
ist noch recht provisorisch, aber prinzipiell klappt es.
Viele Grüße!


Edit: Ich habe diesen Record auch schon erstellt. Ich habe mir nur noch nicht überlegt, wie der Nutzer die Werte dann eintragen kann. Darum getrennt. Die Tags hab ich oben nur vergessen :oops:

sx2008 26. Sep 2010 12:17

AW: Maximale Arraylänge?
 
Ist Dir schon mal aufgefallen, dass dein Sourcecode nur so von Zahlen wimmelt?
Hier ein Beispiel:
Delphi-Quellcode:
 i:=10 {<=};
          while i<width-40{<=} do
                begin
                     G.canvas.Font.size:=5{<=};
                     if (i<x-20{<=}) or (i>x+20{<=}) then G.canvas.TextOut(i,Y-10{<=},FloatToStrf(PixelsToXY(i,i).x,fffixed,10,2));
                     i:=i+50{<=};
                end;
Das führt natürlich zu einer schlechten Codequalität.
Ersetze mal alle diese Zahlen durch Konstanten.
Manche Zahlen sollten sogar durch Variablen ersetzt werden.
Anstatt die Achsen-Beschriftung mit fester Schrittgrösse 5 zu zeichnen,
wäre es doch besser den Font (inkl. Name, Style,...) von aussen vorzugeben.

Delphi-Narr 26. Sep 2010 12:23

AW: Maximale Arraylänge?
 
Wie gesagt, das ist noch ein Provisorium. Aber die Achsen werden immer ordnungsgemäß gezeichnet. Auch bei Arraylänge über 199.
Außerdem ist es doch egal ob ich 10 oder Randabstand hinschreibe. Nur wenn der Abstand geändert werden soll, muss ich halt 4 Zeilen ändern statt einer.
Daran kanns aber nicht liegen.

Viele Grüße!

Satty67 26. Sep 2010 12:26

AW: Maximale Arraylänge?
 
Der für das Problem relevante Teil mal etwas freigestellt:
Delphi-Quellcode:
     SetLength(PS,l);

     for i:=0 to l-1 do
     begin
          PS[i]:=XYtoPixels(XV[i],YV[i]);
     end;

     [...]

     //Graphen zeichnen
     if GraphKind=gkstraight then
     begin
          G.canvas.pen.color:=clred;
          G.canvas.Polyline(Ps);
     end
     else

     if GraphKind=gkrounded then
     begin
          G.canvas.pen.color:=clred;
          G.canvas.Polybezier(Ps);
     end;
Da erkenne ich jetzt kein Fehler, das Polyline eine Obergrenze an hat, ist mir auch nicht bekannt.

Bei SetLength mal einen Breakpoint setzen und auch die Größe von XV/YV testen. Wenn die schon bei 199 Werten stehen bleiben, die Zuweisung dort prüfen (Der Code fehlt leider).

PS: Zeigen die Setter X/YValues direkt auf ein Array oder gibt es eine SetFunktion?

himitsu 26. Sep 2010 12:27

AW: Maximale Arraylänge?
 
Zitat:

Zitat von mkinzler (Beitrag 1052007)
Die Grenze sollten die Größe des größten Verfügbaren Speicherbereichs sein.

rein theoretisch ist die größe maximal
Delphi-Quellcode:
($7FFFFFFF - 8) div SizeOf(arr[0])
Felder,
aber praktisch ist die größe auf den größten zusammenhängenden freien Speicherbereich im virtuellen Speicher der Anwendung und auf den maximalen freien Speicher im physischen Arbeitsspeicher (RAM + Pagefile) begrenzt.

Wenn es also bei diesen läppischen 1800 Byte (200 * SizeOf(Real)) schon knallt, dann ist entweder der virtuelle Speicher deiner Anwendungs hoffnungslos überfüllt und du kannst froh sein, daß die Anwendung überhaupt bit dahin gelaufen ist
oder du solltest nach anderen Ursachen suchen, wie
- fehlerhafte Pointer
- Speicherlecks
- Pufferüberläufe
- falsche Indize


Als erstes empfehle ich einfach mal die Index- und die Bereichsprüfung in den Projektoptionen zu aktivieren und dann auch mal FastMM zu installieren und nach Speicherlecks zu suchen und/oder ein anderes Speicherüberwachungstoll zu verwenden.

xZise 26. Sep 2010 12:28

AW: Maximale Arraylänge?
 
Was ist, wenn das
Delphi-Quellcode:
G1
einfach nicht mehr als 199 Werte aufnehmen kann? Was ist das überhaupt?

Außerdem könnten auch die Zahlen da Probleme machen, dass du irgendwo unabsichtlich was abschneidest. Auch sollten mindestens 200 real-Werte verfügbar sein. Ich würde da einfach erst mal kürzen.

MfG
Fabian

Matze 26. Sep 2010 12:29

AW: Maximale Arraylänge?
 
Anstelle des Datentype "Real" würde ich persönlich übrigens "Double" nutzen.
Intern ist der Datentyp identisch:
Delphi-Quellcode:
// Quelle: http://docwiki.embarcadero.com/VCL/en/System.Double
type Real = Double;
Ich habe den Eindruck, "Real" gibt es nur noch aus Kompatibilitätsgründen.

Delphi-Narr 26. Sep 2010 12:41

AW: Maximale Arraylänge?
 
Also ich habe jetzt den Fehler gefunden... Es liegt an Polybezier. Anscheinend gibt es da eine Obergrenze. Polyline klappt mit 300 Werten auch. Ich prüfe mal auf höhere Werte...

Polyline klappt mit 10000 Werten auch noch. Dann werde ich jetzt halt mehrere Polylines aneinanderreihen.
Viele Grüße!

Satty67 26. Sep 2010 12:59

AW: Maximale Arraylänge?
 
Zitat:

Zitat von Matze (Beitrag 1052032)
Ich habe den Eindruck, "Real" gibt es nur noch aus Kompatibilitätsgründen.

Wenn ein 64bit Compiler kommt, wird es ganz lustig. Integer und Cardinal sind ja auch nur generische Typen. Da müsste dann laut Definition der Integer von Longint zum Int64 werden. Genau genommen ist Integer zu verwenden also genauso riskant wie Real, außer die Größe des Typen ist nicht wirklich relevant.

Ich nehme gerne Double und Word, nur beim signed nehme ich immer Integer statt LongInt... logisch ist das ja auch nicht. Entweder man nimmt Real, Cardinal und Integer oder gleich Double, LongWord und LongInt.

Luckie 26. Sep 2010 13:07

AW: Maximale Arraylänge?
 
Zitat:

Zitat von Delphi-Narr (Beitrag 1052024)
Außerdem ist es doch egal ob ich 10 oder Randabstand hinschreibe. Nur wenn der Abstand geändert werden soll

Ist es nicht. Ich bin mir ziemlich sicher, dass du in einem halben Jahr nicht mehr weißt, wo du überall den Randwert setzt. Und außerdem musst du die vier, noch sind es vier Stellen, finden. Und besonders lustig wird es, wenn an mehreren Stellen die 10 vorkommt.

Und später heißt es dann wieder hier im Forum: "Ich habe nur was geändert und jetzt funktioniert es nicht mehr." Und nach seitemlangen Fehlersuchen und verzweifelten Hilfeversuchen, stellt sich dann raus, dass der Fehler durch so unsauberen Code zustande gekommen ist.

Delphi-Narr 26. Sep 2010 13:42

AW: Maximale Arraylänge?
 
Zitat:

Zitat von Luckie (Beitrag 1052071)
Zitat:

Zitat von Delphi-Narr (Beitrag 1052024)
Außerdem ist es doch egal ob ich 10 oder Randabstand hinschreibe. Nur wenn der Abstand geändert werden soll

Ist es nicht. Ich bin mir ziemlich sicher, dass du in einem halben Jahr nicht mehr weißt, wo du überall den Randwert setzt. Und außerdem musst du die vier, noch sind es vier Stellen, finden. Und besonders lustig wird es, wenn an mehreren Stellen die 10 vorkommt.

Und später heißt es dann wieder hier im Forum: "Ich habe nur was geändert und jetzt funktioniert es nicht mehr." Und nach seitemlangen Fehlersuchen und verzweifelten Hilfeversuchen, stellt sich dann raus, dass der Fehler durch so unsauberen Code zustande gekommen ist.

Ich kenne meine Codes eigentlich alle ziemlich gut und sehe mich in der Lage, meine Codes auch nach zwei Jahren noch zu verstehen. Außerdem handelt es sich hierbei um eine Komponente, die nach der Entwicklung eh meistens nicht mehr geändert wird. Aber ich änder das trotzdem gerne, wenn du es besser findest ;)

Luckie 26. Sep 2010 14:01

AW: Maximale Arraylänge?
 
Zitat:

Zitat von Delphi-Narr (Beitrag 1052091)
Ich kenne meine Codes eigentlich alle ziemlich gut und sehe mich in der Lage, meine Codes auch nach zwei Jahren noch zu verstehen.

OK, lass uns in zwei Jahren den Code noch mal angucken. ;)

Zitat:

Außerdem handelt es sich hierbei um eine Komponente, die nach der Entwicklung eh meistens nicht mehr geändert wird.
Ok, dann machen wir aus den zwei Jahren fünf Jahre. ;) Und damit steigt die Wahrscheinlichkeit, dass ein andere Programmierer den Code in die Finger bekommt. Und was ist dagegen einzuwenden die Lesbarkeit und die Wartbarkeit für sich und andere zu erhöhen?

xZise 26. Sep 2010 14:10

AW: Maximale Arraylänge?
 
Zitat:

Zitat von Delphi-Narr (Beitrag 1052091)
[...]Ich kenne meine Codes eigentlich alle ziemlich gut und sehe mich in der Lage, meine Codes auch nach zwei Jahren noch zu verstehen. Außerdem handelt es sich hierbei um eine Komponente, die nach der Entwicklung eh meistens nicht mehr geändert wird. Aber ich änder das trotzdem gerne, wenn du es besser findest ;)

Du wirst es auch besser finden, weil er auch lesbarer ist. Und sobald du einen Wert mehrmals verwendest brauchst du nur die Konstante zu ändern und es funktioniert alles.

Also ich würde mir nicht trauen diese eine Theorie zu nennen. Ich habe den Überblick bei einem Programm nach 1 Jahr schon fast verloren. Inzwischen habe ich mich wieder eingearbeitet, aber anfangs war das nur rätselraten was was macht. Und dann musst du schnell einen Fehler finden.

MfG
Fabian

Delphi-Narr 27. Sep 2010 15:15

AW: Maximale Arraylänge?
 
Bei komplexen Programmen mag das Rätselraten stimmen. Doch bei einem so einfachen Code sollte das Verstehen kein allzu großes Problem darstellen. Aber ich habe jetzt die Konstante "Rand" mit Wert 10 eingeführt :thumb:

Noch eine Frage nebenbei: Ich habe das Ganze als Unterart von TPanel erstellt. Natürlich habe ich einen eigenen constructor geschrieben. Doch wenn ich
Delphi-Quellcode:
self.caption:=''
setze, nachdem ich

Delphi-Quellcode:
inherited Create(AOwner);
aufgerufen habe, bleibt die Caption immer noch auf der Standardaufschrift. Wie kann ich das ändern? Oder neues Thema? :?::?::?:

Viele Grüße!

shmia 27. Sep 2010 15:36

AW: Maximale Arraylänge?
 
Zitat:

Zitat von Delphi-Narr (Beitrag 1052388)
Doch bei einem so einfachen Code sollte das Verstehen kein allzu großes Problem darstellen.

Funktionsplotter sollte man nicht unterschätzen; das kann je nach Umfang der Möglichkeiten ganz schön komplex werden.

Zitat:

Zitat von Delphi-Narr (Beitrag 1052388)
Ich habe das Ganze als Unterart von TPanel erstellt.

Besser wäre eine eigene Klasse.
Die Klasse bekommt (unter anderem) folgende Informationen:
* ein Canvas auf dem gezeichnet werden soll
* ein TRect, dass die Grenzen in Pixel angibt innerhalb derer gezeichnet wird.
Dadurch kann man in ein Image zeichen oder auf dem Drucker-Canvas oder in einer TGraphicControl oder in eine Paintbox.
Ausserdem kann man mehrere Graphen neben-/untereinander erzeugen.
Wenn man's richtig macht ergeben sich ganz neue Möglichkeiten!!

Zitat:

Zitat von Delphi-Narr (Beitrag 1052388)
Doch wenn ich
Delphi-Quellcode:
self.caption:=''
setze....

Das liegt möglicherweise daran, dass deine Komponente schon auf dem Formular liegt und das Property in der DFM-Datei gespeichert wird.


Alle Zeitangaben in WEZ +1. Es ist jetzt 15:11 Uhr.

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