Autor Beitrag
Pyromane
Hält's aus hier
Beiträge: 4



BeitragVerfasst: Mi 17.12.08 19:48 
Ahoi,
ich habe hier ein Programm mit mehreren Formularen.
In einem dieser Formulare läuft ein Primzahlsieb...

ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
...
TDynBoolArray=array of Boolean;
...
implementation

procedure Sieb(max:integer);
var i,k:integer;
begin
  SetLength(feld,max-2);
  For i:=2 to max do feld[i-2]:=true;
  For i:=2 to round(sqrt(max)+1do
        For k:=i to round(max/i) do
           feld[i*k]:=false;
end;

procedure TForm_Sieb.Button1Click(Sender: TObject);
var max,err,i:integer;

begin
val(Sieb_ED_max.text,max,err); {Sieb_ED_max ist ein Edit-Feld}
if err<>0 then ShowMessage('Fehlerhafte Eingabe!'else
  if max > 1 then begin
      Listbox1.Clear; {LB löschen}
      Sieb(max);
      for i:=2 to max do if feld[i-2then Listbox1.Items.Add(inttostr(i));
                  end
  else ShowMessage('Nur Zahlen größer 1 eingeben!');
end;

procedure TForm_Sieb.FormClose(Sender: TObject; var Action: TCloseAction);
begin
setlength(feld,0);
end;


das ist jetzt eine vereinfachte Version, eig. sollte die Sieb-Prozedur als Funktion in einer anderen Unit laufen und der Return-Array dann kopiert werden, doch da hat man nicht so gut durchgesehen ;)

-> Wenn ich das ausführe sürtzt das Programm immer mit einem InvalidPointer Error ab, egal wo ich das SetLength(Feld,0) setze
(also a) im Form_Sieb.Close, b) direkt nach dem schreiben, c) garnicht -> Dann wird es beim schließen der Mainform automatisch gemacht.)

sieht wer den Fehler?
MfG Pyromane

Moderiert von user profile iconChristian S.: Code- durch Delphi-Tags ersetzt
turboPASCAL
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 193
Erhaltene Danke: 1

Win XP / Vischda
D6 PE / D2005 PE
BeitragVerfasst: Mi 17.12.08 20:35 
Und Feld ist wie deklariert ?


ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
procedure Sieb(max:integer);
var i,k:integer;
begin
  SetLength(feld,max-2); // <--<<
  For i:=2 to max do feld[i-2]:=true;
  For i:=2 to round(sqrt(max)+1do
        For k:=i to round(max/i) do
           feld[i*k]:=false;
end;


Hier wird das Array ungeprüft verkleinert.

_________________
Nein, ich bin nicht der turboPASCAL aus der DP, ich seh nur so aus... :P


Zuletzt bearbeitet von turboPASCAL am Mi 17.12.08 20:38, insgesamt 1-mal bearbeitet
Xentar
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 2077
Erhaltene Danke: 2

Win XP
Delphi 5 Ent., Delphi 2007 Prof
BeitragVerfasst: Mi 17.12.08 20:36 
Dein Array ist auch voll unterdimensioniert..

Edit: Ne, nicht unterdimensioniert - du rechnest nur komisch. Wieso i*k?

Angenommen, man hackt 9 als Wert ein.
Dann läuft die äußere for schleife (i, Zeile 11) bis Wurzel(9)+1 = 4
und die innere dann im schlimmsten Fall, also im ersten Durchgang bis round(9 / 2) = round(4,5) = 5

Du greifst also auf Speicherstelle 4*5 = 20 zu.. es gibt aber nur 7.. ups ;)
Dadurch überschreibst dir ganz toll irgendeinen Speicherbereich.


Für sowas gibts übrigens die Bereichsprüfung (Projektoptionen -> Debugger), sowie Haltepunkte..


Edit: Ahhhh, mein Fehler. Die Innere Schleife fängt ja bei K an, nicht bei 2. Verlesen :( Ok, dann ist mein Geschreibsel da oben hinfällig. Solltest trotzdem mal Zeile für Zeile durchgehen, und dir die Variablen anschauen.

_________________
PROGRAMMER: A device for converting coffee into software.


Zuletzt bearbeitet von Xentar am Mi 17.12.08 23:28, insgesamt 1-mal bearbeitet
Pyromane Threadstarter
Hält's aus hier
Beiträge: 4



BeitragVerfasst: Mi 17.12.08 23:17 
OOps das deklarieren hab ich vergessen zu Posten:

var feld:TDynBoolArray;
steht über dem Implementation Bereich;
Und das mit dem Überschreiben sollte eig. nicht auftreten .. und wenn doch, was soll der Absturz beim Löschen denn mit dem Überschreiben irgendwelcher Variablen zu tun haben?
MfG Pyromane
Xentar
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 2077
Erhaltene Danke: 2

Win XP
Delphi 5 Ent., Delphi 2007 Prof
BeitragVerfasst: Mi 17.12.08 23:25 
Nein, du musst das Array beim Beenden nicht auf 0 setzen.

Und hast du mal meinen Tipp mit der Bereichsprüfung ausprobiert? Dann sagt dir Delphi sogar, wo der Fehler auftritt..
- Bereichsprüfung rein -> Projekt neu erzeugen -> Starten

_________________
PROGRAMMER: A device for converting coffee into software.
Pyromane Threadstarter
Hält's aus hier
Beiträge: 4



BeitragVerfasst: Do 18.12.08 00:08 
Mhh also ich habs so gelernt ;) Unter; Guter Programmierstil *gg* und naja da es das Programm am Ende eh macht stürzt es ja trotzdem ab.
Bei der Prüfung bin ich grade dabei,,, wo zeigt es dann die Ergebnisse an?
So far Pyromane

Mhh hast recht es wird an einer Stelle überschritten... - Aber warum kommt an dieser Stelle kein Fehler? Achso mhh dyn. Arrays ich wusste da war was ;)Delphi geht mit denen ja sehr Stiefmütterlich um.

EDIT: Es wird sogar ziemlich Pöse überschritten ;)
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19341
Erhaltene Danke: 1752

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Do 18.12.08 00:47 
Die Prüfung solltest du übrigens wenn das Programm fertig ist wieder deaktivieren, die macht alle Zugriffe auf dynamische Arrays nämlich langsamer (weil jedesmal auch der Prüfcode ausgeführt wird).