Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Fehlermeldung "Zu wenig Arbeitsspeicher" (https://www.delphipraxis.net/118362-fehlermeldung-zu-wenig-arbeitsspeicher.html)

DerAndereMicha 6. Aug 2008 12:56


Fehlermeldung "Zu wenig Arbeitsspeicher"
 
Hallo Zusammen,

in einer Funktion von mir, die dazu dient aus einer SQL-Anweisung (als Stringliste) alle Kommentare zu entfernen, tritt sporadisch der Fehler "Zu wenig Arbeitsspeicher" auf. Leider kann ich nicht nachvollziehen, wo und warum das geschieht. Evtl. hat einer von Euch ja mehr Überblick und sieht auf den 1.Blick, unter welchen Umständen das passieren könnte bzw. ob ich ansich einen schweren Fehler begehe (evl. die Übergabe der Stringliste?).

Delphi-Quellcode:
function DeleteComments(TempList:TStringList):TStringList;
var beg,en,i : integer;
begin
    for i:=0 to TempList.Count-1 do
       if Trim(Copy(TempList[i],1,2))='--' then
         TempList[i]:='/*'+Copy(TRIM(TempList[i]),3,Length(TempList[i]))+'*/';

    while pos('/*',TempList.Text) <> 0 do
    begin
      beg:=pos('/*',TempList.Text);
      en:=pos('*/',TempList.Text);
      if en=0 then en:=Length(TempList.Text);
      TempList.Text:=copy(TempList.text,1,beg-1)+
                     copy(TempList.Text,en+2,Length(TempList.Text));
    end;
    Result:=TempList;
end;
Gruß
Micha

Phoenix 6. Aug 2008 13:01

Re: Fehlermeldung "Zu wenig Arbeitsspeicher"
 
Ich glaube nicht, dass es an der Übergabe liegt.
Aber warum gibst Du die Instanz von Templist zurück?
Wenn Du doch eh auf der Liste Veränderungen vornimmst, dann brauchst Du sie nicht zurückzugeben.

Delphi-Quellcode:
procedure Machwas;
var
 myListe: TStringList;
begin
  myListe := TStringList.Create();
  try
    // hier noch die liste füllen...


    // der Aufruf
    myListe := DeleteComments(myListe);

    // ist vollkommen identisch mit:
    DeleteComments(myListe);

  finally
    if Assigned(myListe) then
      FreeAndNil(myListe);
  end;
end;

DerAndereMicha 6. Aug 2008 13:09

Re: Fehlermeldung "Zu wenig Arbeitsspeicher"
 
Ok, schon geändert.

Macht es eigentlich einen Unterschied ob man:

Delphi-Quellcode:
procedure DeleteComments(TempList:TStringList);
oder

Delphi-Quellcode:
procedure DeleteComments(var TempList:TStringList);

deklariert.

Gruß
Micha

DeddyH 6. Aug 2008 13:16

Re: Fehlermeldung "Zu wenig Arbeitsspeicher"
 
Ja, denn bei der Übergabe als var kannst Du theoretisch sogar die Referenz ändern, d.h. wenn Du ListBox.Items übergibst, könntest Du auf ComboBox.Items referenzieren. Daher habe ich persönlich mir angewöhnt, Objektinstanzen immer als const-Parameter zu übergeben.

DerAndereMicha 6. Aug 2008 13:23

Re: Fehlermeldung "Zu wenig Arbeitsspeicher"
 
Alles klar und vielen Dank.

Aber woher könnte denn nun die Fehlermeldung kommen?

DeddyH 6. Aug 2008 13:27

Re: Fehlermeldung "Zu wenig Arbeitsspeicher"
 
Übergibst Du jetzt als const-Parameter?

Phoenix 6. Aug 2008 13:33

Re: Fehlermeldung "Zu wenig Arbeitsspeicher"
 
Für mich gerade logische Erklärung:
Du benutzt ziemlich intensiv 'copy'. Das erzeugt eine String-Variable. Da Du das Ergebnis sofort verwendest und nirgends 'manuell' zwischenspeicherst, muss Delphi die Variable ja irgendwo hinpacken. Jedes einzelne Copy braucht also Speicher, der solange belegt wird, bis die Funktion beendet ist. (Kann auch sein, dass ich mich hier irre. Ich kenne die interna dafür nicht gut genug).

Möglicherweise hilft es, mit temporären Variablen zu arbeiten, und zuerst die Rückgabe von Copy dort abzulegen und dann erst dann zu vergleichen, als das in einem Schritt zu machen. Somit hat der Wert der aus Copy rauskommt einen genau definierten Platz im Speicher und überschreibt immer den vorherigen, anstelle neuen Platz zu benötigen (wie gesagt ohne Gewähr für die Richtigkeit meiner Annahme).

DeddyH 6. Aug 2008 13:35

Re: Fehlermeldung "Zu wenig Arbeitsspeicher"
 
Klingt logisch.

Phoenix 6. Aug 2008 13:36

Re: Fehlermeldung "Zu wenig Arbeitsspeicher"
 
Zitat:

Zitat von DeddyH
Klingt logisch.

Kann aber genausogut grottenverkehrt sein ;-)

DerAndereMicha 6. Aug 2008 13:36

Re: Fehlermeldung "Zu wenig Arbeitsspeicher"
 
Ja, das hab ich geändert. Das Problem ist aber, daß der Fehler bei mir selbst sowieso noch nie aufgetreten ist; also nicht vor und auch nicht nach der jetzigen Änderung. Der Fehler tritt nur sporadisch (1-5 mal pro Monat) bei dem Benutzer der Software auf und so ist das schwierig herauszufinden, ob es was gebracht hat.

Du meinst aber also schon, daß es daran gelegen haben könnte?

Gruß
Micha

DeddyH 6. Aug 2008 13:38

Re: Fehlermeldung "Zu wenig Arbeitsspeicher"
 
Versuch es mal mit Zwischenspeichern der Teilstrings wie von Phoenix angesprochen.

DerAndereMicha 6. Aug 2008 13:40

Re: Fehlermeldung "Zu wenig Arbeitsspeicher"
 
@DeddyH: Ich hatte Phoenix' Antwort noch nicht gelesen, als ich Dir geantwortet habe, sorry.

@Phoenix: Kannst Du mir dafür mal ein Beispiel geben? Ich glaub ich verstehs gerade nicht so richtig ... habe um die Uhrzeit glaube immer meinen Tiefpunkt :-)

Gruß
Micha

sx2008 6. Aug 2008 13:42

Re: Fehlermeldung "Zu wenig Arbeitsspeicher"
 
Also ich würde so vorgehen:
1.) alle Zeilen, die mit '--' beginnen enfernen.
Delphi-Quellcode:
for i:=TempList.Count-1 downto 0 do // rückwärts zählen !!
  if Trim(Copy(TempList[i],1,2))='--' then
    TempList.Delete(i);
2.) TempList.Text ist Stringvariable kopieren, damit arbeiten/ändern und Ergebnis zurückkopieren.
(so wie Phoenix das erklärt hat)

>> daß es daran gelegen haben könnte ?
Wichtig ist das Bottom-Up Design.
Die Procedure wird solange umgebaut/verbessert bis mehrere Programmierer sie für
gut und richtig befinden.
Das gibt Sicherheit und eine gute Basis für ein Projekt.

DeddyH 6. Aug 2008 13:49

Re: Fehlermeldung "Zu wenig Arbeitsspeicher"
 
Zitat:

Zitat von sx2008
Delphi-Quellcode:
for i:=TempList.Count-1 downto 0 do // rückwärts zählen !!

Wieso? Solange keine Zeilen gelöscht werden (und sich dadurch TempList.Count ändert), kann IMHO nichts passieren.

DerAndereMicha 6. Aug 2008 14:02

Re: Fehlermeldung "Zu wenig Arbeitsspeicher"
 
Ich hab jetzt mal alles so geändert, wie ich es verstanden hab und bitte hiermit um erneute Überprüfung (ganz im Sinne des Bottom-Up Designs)

Delphi-Quellcode:
function DeleteCommentsNeu(const SQLLines:TStringList):Boolean;
var beg,en,i,Laenge : integer;
var Temp,begStr,enStr:String;
begin
    Laenge:=Length(SQLLines.Text);
    for i:= SQLLines.Count-1 downto 0 do
    Begin
       Temp:=Copy(Trim(SQLLines[i]),1,2);
       if Temp='--' then SQLLines.Delete(i);
    end;

   Temp:=SQLLines.Text;
   while (pos('/*',Temp) <> 0) and
     (pos('*/',Temp)>pos('/*',Temp)) do
   begin
      beg:=pos('/*',Temp);
      en:=pos('*/',Temp);
      if en=0 then en:=Length(Temp);

      begStr:=copy(Temp,1,beg-1);
      enStr:= copy(Temp,en+2,Length(Temp));

      Temp:=begStr+enStr;
   end;
   SQLLines.Text:=Temp;
   Result:=Length(SQLLines.Text)<>Laenge;
end;
Gruß
Micha

OldGrumpy 6. Aug 2008 14:09

Re: Fehlermeldung "Zu wenig Arbeitsspeicher"
 
Zitat:

Zitat von DeddyH
Zitat:

Zitat von sx2008
Delphi-Quellcode:
for i:=TempList.Count-1 downto 0 do // rückwärts zählen !!

Wieso? Solange keine Zeilen gelöscht werden (und sich dadurch TempList.Count ändert), kann IMHO nichts passieren.

Ja, genau so sieht das aus. Und jetzt schau nochmal auf den fett hervorgehobenen Teil :)

Zitat:

Zitat von sx2008
Code:
for i:=TempList.Count-1 downto 0 do // rückwärts zählen !!
  if Trim(Copy(TempList[i],1,2))='--' then
    [b]TempList.Delete(i);[/b]


DeddyH 6. Aug 2008 14:12

Re: Fehlermeldung "Zu wenig Arbeitsspeicher"
 
Sieht auf den ersten Blick gut aus, allerdings löschst Du keine einzeiligen Kommentare am Zeilenende.

[edit] @Grumpy: das ist mir später dann auch aufgefallen :lol: [/edit]

DerAndereMicha 6. Aug 2008 14:17

Re: Fehlermeldung "Zu wenig Arbeitsspeicher"
 
So sieht's tatsächlich aus. Danke, ich werd's gleich noch ändern.

Gruß
Micha

DerAndereMicha 6. Aug 2008 14:26

Re: Fehlermeldung "Zu wenig Arbeitsspeicher"
 
So, fertig:

Delphi-Quellcode:
function DeleteCommentsNeu(const SQLLines:TStringList):Boolean;
var beg,en,i,Laenge : integer;
var Temp,begStr,enStr:String;
begin
    Laenge:=Length(SQLLines.Text);
    for i:= SQLLines.Count-1 downto 0 do
    Begin
      beg:=pos('--',SQLLines[i]);
      if beg <> 0 then
      Begin
        if beg=1 then SQLLines.Delete(i)
        else SQLLines[i]:=Copy(SQLLines[i],1,beg-1);
      end;
    end;

   Temp:=SQLLines.Text;
   while (pos('/*',Temp) <> 0) and
     (pos('*/',Temp)>pos('/*',Temp)) do
   begin
      beg:=pos('/*',Temp);
      en:=pos('*/',Temp);
      if en=0 then en:=Length(Temp);

      begStr:=copy(Temp,1,beg-1);
      enStr:= copy(Temp,en+2,Length(Temp));

      Temp:=begStr+enStr;
   end;
   SQLLines.Text:=Temp;
   Result:=Length(SQLLines.Text)<>Laenge;
end;
Gruß
Micha

DeddyH 6. Aug 2008 14:30

Re: Fehlermeldung "Zu wenig Arbeitsspeicher"
 
Kleiner Vorschlag:
Delphi-Quellcode:
for i:= SQLLines.Count-1 downto 0 do
    Begin
      beg:=pos('--',Trim(SQLLines[i]));
Und
Zitat:

Delphi-Quellcode:
if beg <> 0 then
      Begin
        if beg=1 then SQLLines.Delete(i)
        else SQLLines[i]:=Copy(SQLLines[i],1,beg-1);
      end;

könnte man auch durch case ersetzen, ist aber nicht unbedingt nötig. Ansonsten teste ich das heute Abend mal zu Hause :zwinker:

p80286 6. Aug 2008 15:31

Re: Fehlermeldung "Zu wenig Arbeitsspeicher"
 
Hallo Micha,
ich vermute das ist nicht so gewollt:
Zitat:

begin
beg:=pos('/*',Temp);
en:=pos('*/',Temp);
if en=0 then en:=Length(Temp);
Dies würde bedeuten, wenn '*/' ,aus welchen Gründen auch immer, fehlt dann wird gnadenlos bis zum Ende gelöscht!

und ob es hiermit keinen Ärger gibt weiß ich auch nicht:
Zitat:

enStr:= copy(Temp,en+2,Length(Temp));
Ich weiß nicht ob in Deinen Daten solche Konstrukte möglich sind:
Delphi-Quellcode:
Select Daten
/* ab hier jetzt auswählen
-- ,daten1
-- ,daten2
-- ,daten3
-- Bitte das Datumsformat beachten !! */
from .......
es gibt Clients, die so etwas verdauen können. In diesem Fall handelst Du Dir durch das löschen der Zeilenkommentare '--' eine Menge Ärger ein, weil dann nur noch "Select Daten" übrig bleibt.

Gruß
K-H

spaxxn 6. Aug 2008 15:44

Re: Fehlermeldung "Zu wenig Arbeitsspeicher"
 
:stupid:

DerAndereMicha 6. Aug 2008 15:46

Re: Fehlermeldung "Zu wenig Arbeitsspeicher"
 
Hallo p80286,

1. Ich denke durch die Bedingung

Delphi-Quellcode:
(pos('*/',Temp)>pos('/*',Temp))
in der WHILE-Schleife, sollte die IF-Anweisung

Delphi-Quellcode:
if en=0 then en:=Length(Temp);
gar nicht auslösen - ist quasi eine Altlast.

2. Warum sollte die Zeile

Delphi-Quellcode:
enStr:= copy(Temp,en+2,Length(Temp));
Ärger bringen?

3. Da geb ich Dir recht und werd mir was überlegen.


Gruß
Micha

DerAndereMicha 6. Aug 2008 15:46

Re: Fehlermeldung "Zu wenig Arbeitsspeicher"
 
Hallo spaxxn,

na und?

Gruß
Micha

p80286 6. Aug 2008 15:58

Re: Fehlermeldung "Zu wenig Arbeitsspeicher"
 
Hallo Micha,

da en+2 größer als length(temp) ist.

In der Vergangenheit bin ich damit mal vor die Wand gelaufen darum benutze ich immer

Delphi-Quellcode:
if startpos<=length(daten) then
   dummy:=copy(daten,startpos,lange);
um ganz sicher zu gehen

Delphi-Quellcode:
if (startpos>length(daten)) and (lange>0) then
   dummy:=copy(daten,startpos,lange);
oder
Delphi-Quellcode:
if startpos+lange-1<=length(daten) then
   dummy:=copy(daten,startpos,lange);
Gruß
K-H

nahpets 6. Aug 2008 16:13

Re: Fehlermeldung "Zu wenig Arbeitsspeicher"
 
Hallo,
Zitat:

es gibt Clients, die so etwas verdauen können. In diesem Fall handelst Du Dir durch das löschen der Zeilenkommentare '--' eine Menge Ärger ein, weil dann nur noch "Select Daten" übrig bleibt.
Reihenfolge ändern, erst /* bis */ und dann im Rest noch --

Vorschlag für die Kommentare mit /* */

von hinten nach vorne durch die Liste laufen und wenn ein */ gefunden wurde in der Zeile alles bis einschließlich */ löschen,
dann bis nach vorne weiter alle Zeilen löschen, in denen kein /* vorkommt bis zu der Zeile in der /* vorkommt und in der Zeile alles ab dem /* löschen.

Auch sowas ist möglich:

SQL-Code:
Select
Daten /* ab hier jetzt auswählen
-- ,daten1 
-- ,daten2 
-- ,daten3 
-- Bitte das Datumsformat beachten !! */ from .......
Stelle mir das in etwa so vor (nicht getestet!!!)
Delphi-Quellcode:
bKom := false;
for i := SQLLines.Count-1 downto 0 do begin
  iPosEnde := Pos('*/',SQLLines[i]);
  if iPosEnde > 0 then begin
    s := Copy(SQLLines[i],1,iPosEnde - 1);
    SQLLines[i] := s;
    bKom := True;
  end else begin
    iPosAnfang := Pos('/*',SQLLines[i]);
    if iPosAnfang > 0 then begin
      s := Copy(SQLLines[i],iPosAnfang - 1, length(SQLLines[i]) - iPosAnfang);
      SQLLines[i] := s;
      bKom := False;
    end;
  end;
  if bKom then SQLLines.Delete(i);
end;
for i := SQLLines.Count-1 downto 0 do begin
  bKom := Copy(Trim(SQLLines[i]),1,2) = '--';
  If bKom Then SQLLines.Delete(i)
end;
Du sparst dadurch viele pos auf die ganze Stringliste. Pos ist immer nur für eine Zeile erforderlich, Du brauchst halt zusätzlich einen Schalter zum merken, ob Du in einem Kommentar bist oder nicht.

Stephan

PS.: Dein Speicherproblem muss aber nicht hier liegen, mag sein, das viel Speicher gebraucht wird. Versuche trotzdem heraus´zufinden, was auf dem Rechner zum Zeitpunkt des Fehlers sonst noch so alles unterwegs ist, eventuell läuft ja zuweilen parallel noch ein anderer "Speicherfresser". Im Zweifelsfalle versuche in einem Try-Except-Block herauszubekommen, wie groß die Stringliste ist, wieviel Speicher Dein Programm braucht und wieviel Speicher andere Programme brauchen.

p80286 6. Aug 2008 17:06

Re: Fehlermeldung "Zu wenig Arbeitsspeicher"
 
Hallo zusammen,

ich habe einmal zusammengekramt wie groß unsere SQL-Scripte so sind.
Die meisten liegen bei ca. 1-5K
wenige haben bis zu 50..60K
und ganz wenige mehr als 300K.
Die enthalten dann aber auch gleich ein paar Daten .

Die 300K sollten eigentlich überhaupt kein Problem sein. Wenn ich mich richtig erinnere werden daraus ca. 600K wenn die Datei geladen ist. Da bleibt eigentlich noch genügend Platz für andere Daten und Programme.
(wenn im fraglichen Script allerdings eine vollständige DB-Generierung + Daten steckt, dann allerdings)

Gruß
K-H

DeddyH 6. Aug 2008 17:21

Re: Fehlermeldung "Zu wenig Arbeitsspeicher"
 
Ich hab da auch mal einen Versuch gestartet (könnte aber bei sehr großen Skripten auch ein Speicher- oder Performanceproblem haben):
Delphi-Quellcode:
procedure StripSQLComments(const sl: TStrings);
const cmBegin = '/*';
      cmEnd = '*/';
      cmOneLine = '--';
var i,start,ende: integer;
    temp: string;
begin
  sl.BeginUpdate;
  try
    //Mehrzeilige Kommentare entfernen
    temp := sl.Text;
    start := Pos(cmBegin,temp);
    ende := Pos(cmEnd,temp);
    while (start > 0) and (ende > start) do
      begin
        System.Delete(temp,start,ende - start + Length(cmEnd));
        start := Pos(cmBegin,temp);
        ende := Pos(cmEnd,temp);
      end;
    sl.Text := temp;

    //Einzeilige Kommentare und Leerzeilen entfernen
    for i := sl.Count-1 downto 0 do
      begin
        start := Pos(cmOneLine,Trim(sl[i]));
        case start of
          0: if Length(Trim(sl[i])) = 0 then
               sl.Delete(i);
          1: sl.Delete(i);
          else
            begin
              temp := sl[i];
              System.Delete(temp,start,Length(temp));
              sl[i] := temp;
            end;
        end;
      end;
  finally
    sl.EndUpdate;
  end;
end;

DerAndereMicha 7. Aug 2008 07:10

Re: Fehlermeldung "Zu wenig Arbeitsspeicher"
 
Vielen Dank für Eure viele Antworten und Anregungen, ich werde mir alles im Laufe des Tages mal anschauen und meine Fkt. evtl. entsprechend ändern.

Gruß
Micha

nahpets 7. Aug 2008 07:58

Re: Fehlermeldung "Zu wenig Arbeitsspeicher"
 
Hallo,

mir ist da diese Nacht noch was eingefallen:

Meine oben "aufgeführte" Logik(?) scheitert bei

SQL-Code:
Select
Daten /* ab hier jetzt auswählen
-- ,daten1 
-- ,daten2 
-- ,daten3 
-- Bitte das Datumsformat beachten !! */ from
where spalte1 = 'xyz' /* das ist jetzt Kommentar */ and spalte2 = 42
and datum > '01.01.1900' -- das ist ein Datum für irgendwaszumausschließen
Daher noch ein Vorschlag:

per globaler Ersetzung alle /* in "Zeilenvorschub /* Zeilenvorschub" ändern, ebenso alle */ in "Zeilenvorschub */ Zeilenvorschub" ändern, damit hast Du dann alle Kommentare der *-Sorte am Zeilenanfang, hierdurch dürfte das finden der Kommentare und das Erkennen von Anfang und Ende einfacher werden. Probleme bleiben dennoch:

SQL-Code:
Select * from tabelle where sqlstring like '%/*%'
Da scheitert auch diese Logik. Wie weit musst Du das mit dem Rauswerfen der Kommentare treiben? Und warum müssen sie raus?
Bei Oracle bekämst Du da noch ein zusätzliches Problem: Hinweise an den Optimizer stehen nämlich auch in Kommentaren und die rauszuwerfen wäre suboptimal. Wahrscheinlich mache ich hier aber gerade Baustellen auf, die ruhig zugelassen werden können.
Und ich befürchte, dass hat alles nichts mit dem Speicherproblem zu tuen. Wie groß sind die von Dir zu bearbeitenden Statements und wieviele sind es?

Stephan

jim_raynor 7. Aug 2008 08:39

Re: Fehlermeldung "Zu wenig Arbeitsspeicher"
 
Zitat:

Zitat von Phoenix
Für mich gerade logische Erklärung:
Du benutzt ziemlich intensiv 'copy'. Das erzeugt eine String-Variable. Da Du das Ergebnis sofort verwendest und nirgends 'manuell' zwischenspeicherst, muss Delphi die Variable ja irgendwo hinpacken. Jedes einzelne Copy braucht also Speicher, der solange belegt wird, bis die Funktion beendet ist. (Kann auch sein, dass ich mich hier irre. Ich kenne die interna dafür nicht gut genug).

Ja, diese Erfahrung habe ich auch gemacht. Zumindestens in Delphi 7 ist es tatsächlich so, dass alle temporären Strings die in einer Prozedur anfallen erst am Ende freigegeben werden.

DerAndereMicha 7. Aug 2008 09:53

Re: Fehlermeldung "Zu wenig Arbeitsspeicher"
 
So, ich habe mir alles mal angeschaut und mich entschlossen bei meiner Logik zu bleiben, aber Eure Einwände mit einzubeziehen.

@nahpets: Deine Prozedur hat leider scheinbar auch einige Fehler, jedenfalls liefert Sie nicht immer ein korrektes Ergebis.
z.B. bei

SQL-Code:
       
Select * /* Daten
-- ,daten1
-- ,daten2
-- ,daten3 */ from
Aber es geht ja hier nicht um Deine Prozedur, sondern um meine ;-) Trotzdem Danke für Deine Anregungen.


Deine Anmerkungen hinsichtlich Oracle sind zwar richtig, aber in meinem Fall brauch ich das wohl nicht zu beachten, da ich nur mit dem MS-SQL-Server arbeite.

Das mit:

SQL-Code:
Select * from tabelle where sqlstring like '%/*%'
ist aber allerdings schon ein Problem. Ich denke aber ich kann das vernachlässigen, zumindest bis zur 1.Meldung eines Kunden, der nach diesem String selektieren möchte ;.)

Die Kommentare müssen raus, da sie beim Zugriff mit ADO unter gewissen Umständen zu Problemen führen und ich nicht weiß was mein Kunde in seine SQL-Skripte alles reinschreibt.


@DeddyH: Deine Prozedur funktioniert hervorragend, ist aber deutlich langsamer (bis zu 10x) als meine, sobald es sich um große SQL-Skripte mit vielen Zeilen handelt, ansonsten ist sie schneller.


@Alle
Ansonsten noch mal allen vielen Dank. Ich hoffe die Optimierungen (besonders die COPY-Problematik) haben geholfen und ich sehe den Fehler nie wieder in meinen Fehlerprotokollen.

Gruß
Micha

nahpets 7. Aug 2008 10:17

Re: Fehlermeldung "Zu wenig Arbeitsspeicher"
 
Hallo,
Zitat:

Zitat von DerAndereMicha
@nahpets: Deine Prozedur hat leider scheinbar auch einige Fehler, jedenfalls liefert Sie nicht immer ein korrektes Ergebis.
z.B. bei

SQL-Code:
       
Select * /* Daten
-- ,daten1
-- ,daten2
-- ,daten3 */ from

Ja, sie war nur so mal eben hingeschrieben, wenn zuerst die Kommentare der Form -- gelöscht werden, muss sie scheitern, da dann ein */-Ende weggeworfen wird. Daher mein verspäteter Einwand: Zeilenumbrüche einzubauen, erst die *-Kommentare wegzuwerfen und als "Rest" dann die -- Kommentare.

Zitat:

Zitat von DerAndereMicha
Das mit:

SQL-Code:
Select * from tabelle where sqlstring like '%/*%'
ist aber allerdings schon ein Problem.

Naja, ist schon weit hergeholt (eigentlich), da ich aber bei vielen Programmen die SQL's in einer Datenbanktabelle ablege und sie erst kurz vor der Verwendung im Programm einlese, ist das für mich zuweilen tatsächlich ein Problem, dafür kann ich aber beim Wechsel der Datenbank die SQL's in der Tabelle ändern und muss nicht an's Programm (und das hat durchaus was).

Bin ja nicht neugierig :wink:, aber wie sieht jetzt Deine Lösung aus?

Stephan

DerAndereMicha 7. Aug 2008 11:05

Re: Fehlermeldung "Zu wenig Arbeitsspeicher"
 
Hallo,

ich hab nichts weiter mehr geändert, nur die Reihenfolge der Blöcke vertauscht, die überflüssige IF-Anweisung raus und noch ein try/finaly dazu.

Delphi-Quellcode:
function DeleteCommentsNeu(const SQLLines:TStringList):Boolean;
var beg,en,i,Laenge : integer;
var Temp,begStr,enStr:String;
begin
  Laenge:=Length(SQLLines.Text);
  SQLLines.BeginUpdate;
  Try

   //Mehrzeile Kommentare
   Temp:=SQLLines.Text;
   while (pos('/*',Temp) <> 0) and
     (pos('*/',Temp)>pos('/*',Temp)) do
   begin
      beg:=pos('/*',Temp);
      en:=pos('*/',Temp)+2;

      begStr:=copy(Temp,1,beg-1);
      enStr:= copy(Temp,en,Length(Temp));

      Temp:=begStr+enStr;
   end;
   SQLLines.Text:=Temp;


   //Einzeilige Kommentare
   for i:= SQLLines.Count-1 downto 0 do
   Begin
      beg:=pos('--',SQLLines[i]);
      if beg <> 0 then
      Begin
        if beg=1 then SQLLines.Delete(i)
        else SQLLines[i]:=Copy(SQLLines[i],1,beg-1);
      end;
   end;

  Finally
    SQLLines.EndUpdate;
  End;
  Result:=Length(SQLLines.Text)<>Laenge;
end;
Gruß
Micha

nahpets 7. Aug 2008 11:20

Re: Fehlermeldung "Zu wenig Arbeitsspeicher"
 
Hallo,

einen hätt' ich noch, Du ermittelst die Beginn- und Endepositionen mehrfach, das kann bei großen Datenmengen schon ein bisserl dauern:

Delphi-Quellcode:
 //Mehrzeile Kommentare
   Temp := SQLLines.Text;
   beg := pos('/*',Temp);
   en  := pos('*/',Temp) + 2;
   while (beg <> 0) and (en > beg) do
   begin
      begStr := copy(Temp,1,beg - 1);
      enStr := copy(Temp,en,Length(Temp));
      Temp  := begStr + enStr;
      beg   := pos('/*',Temp);
      en    := pos('*/',Temp) + 2;
   end;
   SQLLines.Text := Temp;
Das könnte eventuell schneller werden.

Stephan

OldGrumpy 7. Aug 2008 11:50

Re: Fehlermeldung "Zu wenig Arbeitsspeicher"
 
Dazu fällt mir noch was ein, ich schreib mal Kommentare in den Code...

Zitat:

Zitat von nahpets
Delphi-Quellcode:
 //Mehrzeile Kommentare
   Temp := SQLLines.Text;
   beg := pos('/*',Temp);
   //wenn beg=0 kann man sich den Rest sparen
   en  := pos('*/',Temp) + 2;
   //mittels PosEx kann man hier auch zeit sparen (en muss hinter beg liegen, also erst ab Position en suchen
   while (beg <> 0) and (en &gt; beg) do
   begin
      begStr := copy(Temp,1,beg - 1);
      enStr := copy(Temp,en,Length(Temp));
      Temp  := begStr + enStr;
      //beg kann jetzt nicht mehr kleiner sein als begStr,
      //daher hier mit PosEx weitersuchen!
      beg   := pos('/*',Temp);
      en    := pos('*/',Temp) + 2;
   end;
   SQLLines.Text := Temp;


DerAndereMicha 7. Aug 2008 12:01

Re: Fehlermeldung "Zu wenig Arbeitsspeicher"
 
"beg" kann nicht 0 sein, daß wird doch schon in der WHILE-Bedingung abgefangen.

Das mit dem PosEx werde ich noch ändern, Danke für den Hinweis.

Gruß
Micha

OldGrumpy 7. Aug 2008 12:12

Re: Fehlermeldung "Zu wenig Arbeitsspeicher"
 
Du hast Recht, ich hatte mir nur das Snippet im letzten Post angeschaut, da ist die umfassende Whileschleife ja nicht mit drin, deswegen hab ichs übersehen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:28 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