Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Für diesen Befehl ist nicht genügend Speicher vorhanden. (https://www.delphipraxis.net/157953-fuer-diesen-befehl-ist-nicht-genuegend-speicher-vorhanden.html)

sventeq 31. Jan 2011 11:05

Für diesen Befehl ist nicht genügend Speicher vorhanden.
 
Hallo zusammen.
Genau diese Fehlermeldung erhalte ich seit heute morgen, wenn diese Procedure starte:

Delphi-Quellcode:
procedure TdiktatNeuDLG.satzEintragenClick(Sender: TObject);
var keineKatZWVorhanden: boolean;
    x: integer;
begin
  ShowMessage(SysErrorMessage(GetLastError));
  keineKatZWVorhanden:=false;
  if Memo1.Text<>'' then
  begin
    if begrenzer<=15 then
    begin
      while length(Memo1.Text) > 0 do
      begin
        if pos(' ', Memo1.Text)<>0 then
        begin
          seObjekt1.dikNeuSilben:=0;
          Text1:=copy(Memo1.Text, 1, pos(' ',Memo1.Text));

          Text1:=copy(Memo1.Text, 1, pos(' ',Memo1.Text));
          delete(Text1, length(Text1), length(Text1));//Leerzeichen löschen

          szeichen:=copy(Text1, length(Text1), length(Text1));
          if (szeichen='.') or (szeichen=',') or (szeichen='!') or (szeichen='?') or (szeichen=':') or (szeichen=';')then
          begin
            delete(Text1, length(Text1), length(Text1));//Satzzeichen entfernen
          end;

          Text2:=Memo1.Text;

          delete(Text2, 1, pos(' ',Memo1.Text));
          Memo1.Text:=Text2;

          eintragWort;
          if (szeichen='.') or (szeichen=',') or (szeichen='!') or (szeichen='?') or (szeichen=':') or (szeichen=';')then
          begin
            seObjekt1.wortID:=seObjekt1.wortID+1;
            eintragSatzzeichen;
            prgrammdb.DikNeuSatzEintrag.Prior;
          end;


          katAuswahlDLG:=TkatAuswahlDLG.Create(self);
          if katAuswahlDLG.showModal=mrOk then
          begin
            katAuswahlDLG.free;
          end;

          //KatZuordnung;
//          KatAbfrage;//Prüfung, ob Kat zugeordnet soll, dann Zuordnung der Kat.

          //Silbenfenster öffnen~~~~~~~~~~~~~~~~~~~~~~~~~
          silbenDLG:=TsilbenDLG.Create(self);
          if silbenDLG.showModal=mrOk then
          begin
            silbenDLG.free;
          end;

          try
            prgrammdb.silben.Open;
          except
            messageDLG('Fehler 1', mtError, [mbOK], 0);
          end;

          if not prgrammdb.silben.IsEmpty then
          begin
            for x := 1 to prgrammdb.silben.RecordCount do
            begin
              if prgrammdb.silben.RecordCount > 1 then
              begin
                try
                  prgrammdb.DikNeuSatzEintrag.Last;
                  prgrammdb.DikNeuSatzEintrag.Insert;
                  prgrammdb.DikNeuSatzEintragDiktatID.Value:=prgrammdb.dikNeuEintragID.Value;
                  prgrammdb.DikNeuSatzEintragWort.Value:=prgrammdb.silbenSilbe.Value;
                  prgrammdb.DikNeuSatzEintragSatzID.Value:=j;
                  prgrammdb.DikNeuSatzEintragWortID.Value:=seObjekt1.wortID;
                  prgrammdb.DikNeuSatzEintragSilbenID.Value:=x;
                  prgrammdb.DikNeuSatzEintrag.Post;
                except
                  messageDLG('Fehler 2', mtError, [mbOK], 0);
                end;
              end;
              //KatZuordnung;
              //showmessage('x: '+inttostr(x)+'  silbe: '+prgrammdb.silbenSilbe.Value+'  WortID: '+inttostr(seObjekt1.wortID));
              prgrammdb.silben.Next;
            end;
            prgrammdb.silben.First;
            while not prgrammdb.silben.Eof do prgrammdb.silben.Delete;
            prgrammdb.silben.Close;
            editSilbenID;
          end;
        end
        else
        begin
          Text1:=copy(Memo1.Text, 1, length(Memo1.Text));

          szeichen:=copy(Text1, length(Text1), length(Text1));
          if szeichen=' ' then delete(Text1, length(Text1), length(Text1));
          szeichen:=copy(Text1, length(Text1), length(Text1));
          if szeichen=' ' then delete(Text1, length(Text1), length(Text1));

          if (szeichen='.') or (szeichen=',') or (szeichen='!') or (szeichen='?') or (szeichen=':') or (szeichen=';')then
          begin
            delete(Text1, length(Text1), length(Text1));//Satzzeichen entfernen
          end;
          Text2:=Memo1.Text;
          delete(Text2, 1, pos(' ',Memo1.Text));
          Memo1.Text:=Text2;

          eintragWort;

          try
            prgrammdb.DikKeineKat.Open;
          except
            messageDLG('Fehler bei der Zusammenstellung der Wörter ohne Kategorie', mtError, [mbOK], 0);
          end;
          prgrammdb.DikKeineKat.First;
          while not prgrammdb.DikKeineKat.Eof do
          begin
            if text1 <> prgrammdb.DikKeineKatWort.Value then keineKatZWVorhanden:=true
            else
            begin
              keineKatZWVorhanden:=false;
              prgrammdb.DikKeineKat.Last;
            end;
            prgrammdb.DikKeineKat.Next;
          end;

//          if keineKatZWVorhanden then
//          begin
//            if MessageDLG('Soll das Wort '+'"'+Text1+'"'+' eine Kategoriezuweisung erhalten?', mtConfirmation,[mbYes, mbNo], 0)=mrNo then
//            begin
//              try
//                prgrammdb.DikKeineKatEintrag.Open;
//                prgrammdb.DikKeineKatEintrag.Insert;
//                prgrammdb.DikKeineKatEintragWort.Value:=Text1;
//                prgrammdb.DikKeineKatEintrag.Post;
//                prgrammdb.DikKeineKatEintrag.Close;
//              except
//                messageDLG('Fehler: Das Wort konnte nicht hinzugefügt werden!', mtError, [mbOK], 0);
//              end;
//            end
//            else KatZuordnung;
//          end;
          Memo1.Text:='';
          //Silbenfenster beim letzten Wort öffnen~~~~~~~~~~~~~~~~~~~~~~
          silbenDLG:=TsilbenDLG.Create(self);
          if silbenDLG.showModal=mrOk then
          begin
            silbenDLG.free;
          end;
          try
            prgrammdb.silben.Open;
          except
            messageDLG('Fehler 1', mtError, [mbOK], 0);
          end;
          if not prgrammdb.silben.IsEmpty then
          begin
            for x := 1 to prgrammdb.silben.RecordCount do
            begin
              if prgrammdb.silben.RecordCount > 1 then
              begin
                try
                  prgrammdb.DikNeuSatzEintrag.Last;
                  prgrammdb.DikNeuSatzEintrag.Insert;
                  prgrammdb.DikNeuSatzEintragDiktatID.Value:=prgrammdb.dikNeuEintragID.Value;
                  prgrammdb.DikNeuSatzEintragWort.Value:=prgrammdb.silbenSilbe.Value;
                  prgrammdb.DikNeuSatzEintragSatzID.Value:=j;
                  prgrammdb.DikNeuSatzEintragWortID.Value:=seObjekt1.wortID;
                  prgrammdb.DikNeuSatzEintragSilbenID.Value:=x;
                  prgrammdb.DikNeuSatzEintrag.Post;
                except
                  messageDLG('Fehler 2', mtError, [mbOK], 0);
                end;
              end;
              //KatZuordnung;
              //showmessage('x: '+inttostr(x)+'  silbe: '+prgrammdb.silbenSilbe.Value+'  WortID: '+inttostr(seObjekt1.wortID));
              prgrammdb.silben.Next;
            end;
            prgrammdb.silben.First;
            while not prgrammdb.silben.Eof do prgrammdb.silben.Delete;
            prgrammdb.silben.Close;
            editSilbenID;
          end;

          if (szeichen='.') or (szeichen=',') or (szeichen='!') or (szeichen='?') or (szeichen=':') or (szeichen=';')then
          begin
            seObjekt1.wortID:=seObjekt1.wortID+1;
            eintragSatzzeichen;
            prgrammdb.DikNeuSatzEintrag.Prior;
          end;
        end;
        seObjekt1.wortID:=seObjekt1.wortID+1;
      end;
      inc(j);
      Memo1.Text:='';
      Memo1.SetFocus;
      inc(begrenzer);
    end
    else
    begin
      showmessage('Es können nicht mehr als 15 Sätze zu einem Diktat hinzugefügt werden.'+ #13+
      'Klicken Sie auf "Schließen", um das Diktat in einem zweiten Teil fortzusetzen.');
    end;
  end
  else showmessage('Bitte geben Sie den Satz ein.');
  prgrammdb.DikKeineKat.Close;
  prgrammdb.diktate.Close;
  prgrammdb.diktate.Open;
end;
Ich weiß, dazu gibt es hier viele Beträge. Allerdings haben die alle meist etwas mit Grafik oder Canvas zu tun. Dies ist bei mit nicht der Fall. Wie man sehen kann, lasse ich die aktuelle Systemfehlermeldung direkt als Erstes nach dem Klick auf den Button ausgeben. Das Merkwürdige ist, dass nach der Fehlermeldung alle Befehle ordnungsgemäß ausgeführt werden. Ich frage mich, warum auf Speicherknappheit hingewiesen wird und warum dann trotzdem alles läuft. Weiß jemand einen Rat?

WM_CLOSE 31. Jan 2011 11:18

AW: Für diesen Befehl ist nicht genügend Speicher vorhanden.
 
Delphi-Quellcode:
GetLastError
muss nicht immer heißen, dass der Fehler innerhalb deiner
Delphi-Quellcode:
procedure
aufgetreten ist.
Er kann auch von woanders kommen. versuche z.b. vor dem Aufruf des Buttons ein
Delphi-Quellcode:
SetLastError
unterzubringen.
Wenn die Meldung immer noch auftritt deutet das darauf hin, dass es ein VCL-Fehler ist, oder dass es innerhalb er VCL ausgewertet wird. Jedenfalls brauchst du dich DANN nicht mehr darum kümmern. Die Anwendung funktioniert deswegen trotzdem.

sventeq 31. Jan 2011 11:25

AW: Für diesen Befehl ist nicht genügend Speicher vorhanden.
 
Zitat:

Zitat von WM_CLOSE (Beitrag 1078511)
Delphi-Quellcode:
GetLastError
muss nicht immer heißen, dass der Fehler innerhalb deiner
Delphi-Quellcode:
procedure
aufgetreten ist.
Er kann auch von woanders kommen. versuche z.b. vor dem Aufruf des Buttons ein
Delphi-Quellcode:
SetLastError
unterzubringen.
Wenn die Meldung immer noch auftritt deutet das darauf hin, dass es ein VCL-Fehler ist, oder dass es innerhalb er VCL ausgewertet wird. Jedenfalls brauchst du dich DANN nicht mehr darum kümmern. Die Anwendung funktioniert deswegen trotzdem.

Ok, versuche ich jetzt mal. Aber wie bekomme ich die Fehlermeldung weg? Obwohl alles funktioniert, wäre es ja schon störend, wenn die Meldung ständig kommen würde.

DeddyH 31. Jan 2011 12:14

AW: Für diesen Befehl ist nicht genügend Speicher vorhanden.
 
Verstehe ich nicht. Du gibst eine Message aus und willst die dann weghaben? BTW:
Zitat:

Delphi-Quellcode:
silbenDLG:=TsilbenDLG.Create(self);
          if silbenDLG.showModal=mrOk then
          begin
            silbenDLG.free;
          end;

Du gibst den Dialog nur frei, wenn er mrOK zurückgibt, erzeugst ihn aber immer neu?

shmia 31. Jan 2011 13:03

AW: Für diesen Befehl ist nicht genügend Speicher vorhanden.
 
Das ist ja mal ein tolles Beispiel, wie man nicht programmieren sollte.
Die Methode ist riesig und hat jede Menge Wiederholungen.
Ausserdem steckt noch auskommentierter Code als Störfeuer drin.

Ok, genug gelästert, hier der Weg zur Besserung.
Ich würde hier ein Bottom-Up-Design vorschlagen; also unten mit den kleinen Dingen beginnen und verbessern.

Ich greife mal diese Zeile raus, die vier Mal vorkommt:
Delphi-Quellcode:
if (szeichen='.') or (szeichen=',') or (szeichen='!') or (szeichen='?') or (szeichen=':') or (szeichen=';')then
begin
Daraus lässt sich eine Funktion erstellen:
Delphi-Quellcode:
function CharIstSatzzeichen(c:char):Boolean;
begin
  result := (c='.') or (c=',') or (c='!') or (c='?') or (c=':') or (c=';');
end;
Mit dem In-Operator lässt sich das noch etwas kompakter schreiben:
Delphi-Quellcode:
function CharIstSatzzeichen(c:AnsiChar):Boolean;
begin
  result := c in ['.',',','!','?',':',';'];
end;
Im nächsten Schritt wird diese Funktion dann verwendet.

Aber damit noch nicht genug. Wir betrachten folgenden Code:
Delphi-Quellcode:
prgrammdb.DikNeuSatzEintrag.Last;
prgrammdb.DikNeuSatzEintrag.Insert;
prgrammdb.DikNeuSatzEintragDiktatID.Value:=prgrammdb.dikNeuEintragID.Value;
prgrammdb.DikNeuSatzEintragWort.Value:=prgrammdb.silbenSilbe.Value;
prgrammdb.DikNeuSatzEintragSatzID.Value:=j;
prgrammdb.DikNeuSatzEintragWortID.Value:=seObjekt1.wortID;
prgrammdb.DikNeuSatzEintragSilbenID.Value:=x;
prgrammdb.DikNeuSatzEintrag.Post;
Dieser Code muss "verschwinden", d.h. er muss in eine Methode wandern:
Delphi-Quellcode:
// Datensatz an Diktionary anhängen
procedure TdiktatNeuDLG.AddDikRecord(DikatID,Word,SatzID,WordID,SilbenID: ???);
Den Datentyp für die Parameter habe ich weggelassen; die kennst du selbst am Besten.
Eigentlich ist der Code noch an der falschen Stelle.
Er gehört zum Datenmodul (oder Formular) Tprgrammdb.

Daniela.S 31. Jan 2011 14:20

AW: Für diesen Befehl ist nicht genügend Speicher vorhanden.
 
ja wenn wir beim Programmstyle schon sind sollte man noch einiges erwähnen...

Also ehrlich gesagt tu ich mir beim Lesen des Codes sehr schwer.
Bisserl umständlich? Und warum 2x hintereinander ein Leerzeichen löschen?
Delphi-Quellcode:
          Text1:=copy(Memo1.Text, 1, length(Memo1.Text));

          szeichen:=copy(Text1, length(Text1), length(Text1));
          if szeichen=' ' then delete(Text1, length(Text1), length(Text1));
          szeichen:=copy(Text1, length(Text1), length(Text1));
          if szeichen=' ' then delete(Text1, length(Text1), length(Text1));
warum nicht so?
Delphi-Quellcode:
  Text1 := Trim( Memo1.Text);


Alle Zeitangaben in WEZ +1. Es ist jetzt 13:04 Uhr.

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