AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

TPerlRegEx - stack overflow

Ein Thema von liftoff · begonnen am 12. Jun 2012 · letzter Beitrag vom 14. Jun 2012
Antwort Antwort
liftoff

Registriert seit: 6. Jun 2012
Ort: Frankfurt am Main
11 Beiträge
 
Delphi XE Enterprise
 
#1

TPerlRegEx - stack overflow

  Alt 12. Jun 2012, 17:21
Hallo zusammen.

Da dies mein erstes Posting hier ist, zunächst mal eine ganz kurze Vorstellung.

Ich bin 44 Jahre alt, männlich und Programmierknecht.

Zur Zeit stelle ich eine über Jahre gewachsene Klassenbibliothek zur Verarbeitung von Swiftnachrichten von Delphi 2007 nach XE um.
Hier hatte ich einige erhellenden Momente im Zusammenhang mit Unicode, welche ich aber soweit in den Griff bekommen habe.
Nur die TPerlRegEx-Klasse macht mir da im Moment noch Probleme. Zuvor habe ich den selben pcre-Unterbau von pcre.org mit einem anderen Wrapper verwendet. Also:

Folgender String
{4:
:16R:XYZ
:20C:ABC
usw. mit insgesamt 482 Zeilen. Am Ende dann:
-}

Matchen soll sich das mit

({4:\r\n(?:[^\r\n]*\r\n)*-})

Der Teil-Ausdruck (?:[^\r\n]*\r\n)* führt zu einem stack overflow. Finde ich bei lümmeligen 482 Zeile etwas merkwürdig.
Mit PCRE 5.x hat das auch jahrelang wunderbar geklappt.

Jemand dazu eine Idee? Vielleicht auch, wie man die Stacksize erhöhen könnte?

Vielen Dank und viele Grüße
  Mit Zitat antworten Zitat
Namenloser

Registriert seit: 7. Jun 2006
Ort: Karlsruhe
3.724 Beiträge
 
FreePascal / Lazarus
 
#2

AW: TPerlRegEx - stack overflow

  Alt 12. Jun 2012, 22:13
Willkommen in der DP

Ich kenne mich mit dem Wrapper und PCRE-Interna nicht aus, aber könnte es daran liegen, dass Unicode-Strings doppelt so viele Bytes pro Zeichen haben wie Ansi-Strings und daher doppelt so viel Platz auf dem Stack benötigt wird?

Die Größe des Stack kann man bei Delphi in den Projekt-Optionen unter Linker einstellen (jedenfalls bei Delphi 2006, bei XE ist der Build-Prozess ja etwas anders).

Oder könnte es sein, dass der neue Wrapper standardmäßig non-greedy statt greedy (oder umgekert?) matcht? Ich sehe zwar auf den ersten Blick nicht, wo das bei diesem Ausdruck einen Unterschied machen sollte, aber wie gesagt kenne ich mich mit den PCRE-Interna nicht aus. Vielleicht einfach mal ausprobieren...

Geändert von Namenloser (12. Jun 2012 um 22:18 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.316 Beiträge
 
Delphi 12 Athens
 
#3

AW: TPerlRegEx - stack overflow

  Alt 12. Jun 2012, 22:31
PCRE gibt es nur für ANSI. (Unicode wird als UTF-8 behandelt).

Es wird hier das originale PCRE von Philip Hazel als *.obj ins Delphi gelinkt. (unter Mac über eine DLL)
Also genau das Selbe, was man in C#, PHP und Co. finden kann.

In Delphi wird daher das Unicode in UTF-8 umgewandelt, also nix mit 2 Byte pro Char,
aber ansonsten ist da nix Besonderes dran. Nur Unicode-UTF8-Konvertierungen und alles in eine Klasse verpackt, aber am Ende nur der originale C++-Code.


Welche Delphi-Edition nutzt du denn genau?
Falls nicht grade die "Starter", dann aktiviere in den Prokjektoptionen mal die DebugDCUs.

Wie sieht der Stacktrace aus?
Und knallt es genau?

Ein Testprojekt hast du nicht zufällig für uns?
Ein Therapeut entspricht 1024 Gigapeut.

Geändert von himitsu (12. Jun 2012 um 22:33 Uhr)
  Mit Zitat antworten Zitat
liftoff

Registriert seit: 6. Jun 2012
Ort: Frankfurt am Main
11 Beiträge
 
Delphi XE Enterprise
 
#4

AW: TPerlRegEx - stack overflow

  Alt 12. Jun 2012, 23:19
Bin gerade nicht im Büro . Auf jeden Fall ist es keine Starter Edition.

Ich habe mir einen Wrapper für den Wrapper geschrieben, damit ich die Orginalsourcen meiner Bibliothek (etwa 15000 Codezeilen) nicht anfassen muss. Diese arbeitet weiterhin mit string, der ja UTF16-codiert ist. Problem war nur die Umwandlung der Matchpositionen von UTF8 nach UTF16. Ein €-Zeichen hat beispielsweise 3 Byte in UTF8 und ein Char (2Byte) in UTF16. Das läuft auch alles prima, solange die zu matchenden Nachrichten nicht zu lang werden.

Mein Problem kann man auch ganz einfach mit der originalen TPerlRegEx nachstellen, also losgelöst von meinem Code.
Es knallt dann direkt beim Aufruf von pcre_exec in TPerlRegEx.Match.
Geliefert wird ein EStackOverflow.

({4:\r\n(?:[^\r\n]*\r\n)*-})

Der Teilausdruck in der Mitte muss ja von pcre_exec intern immer wieder pro Zeile durchgeackert werden. Und irgendwo bei 300 Zeilen (genaue Zahl habe ich jetzt nicht da) ist dann einfach Schluss und die Exception wird ausgeworfen. In meinem Delphi-2007-Wrapper um pcre.obj ist das nicht der Fall.

Entweder ich muss den Ausdruck anfassen, was dann bedeutet, dass ich unter Umständen eine Menge solcher Gefahrenstellen in der Bibliothek habe.
Oder es gelingt irgendwie, die Stackgröße zu erhöhen. Auf pcre.org wird das Thema zwar durchgekaut, allerdings gelingt es mir bisher nicht, dass mit Delphi zu verheiraten.

Wie soll so ein Beispielprojekt aussehen? Könnte ich dann morgen sicherlich noch liefern.
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.603 Beiträge
 
Delphi 12 Athens
 
#5

AW: TPerlRegEx - stack overflow

  Alt 12. Jun 2012, 23:41
Ich kann mich erinnern, daß wir vor Jahren mal ein ähnliches Problem mit TPerlRegEx hatten, das mangels Pascal-Sourcen weder zu debuggen, noch zu beheben war. Die (zumindest damalige) Implementation der RegEx-Enhine war stark rekursiv und brachte bei bestimmten Eingabedateien einen StackOverflow.

Die damalige Lösung bestand darin, auf TPerlRegEx zu verzichten und einen nicht-rekursiven, handgeschriebenen Parser zu verwenden. War auch um Klassen performanter und ließ sich wesentlich besser debuggen.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
liftoff

Registriert seit: 6. Jun 2012
Ort: Frankfurt am Main
11 Beiträge
 
Delphi XE Enterprise
 
#6

AW: TPerlRegEx - stack overflow

  Alt 13. Jun 2012, 11:36
Vielen Dank für die bisherigen Anworten.

Einen eigenen Parser zu schreiben, wäre hier viel zu aufwändig. Das Ganze ist ja bereits ein Parser für Swiftnachrichten auf der Basis von regulären Ausdrücken. In der Tat ist TPerlRegEx ungefähr halb so schnell, wie mein alter Wrapper. Insgesamt ist die Performance aber zufriedenstellend.

Hier dann mal ein Beispielcode:
Code:
var re : TPerlRegEx;
    teststr : UTF8String;
    l1 : integer;
begin
  try
    re := TPerlRegEx.create;
    re.Options := [precaseless];
    re.State := [];

    re.RegEx := '({4:\r\n(?:[^\r\n]*\r\n)*-})';
    re.Compile;

    //    Nun Beispielstring mit Inhalt
    //    {4:
    //    :00X:ABCDEFB0123456789
    //    :00X:ABCDEFB0123456789
    //    :00X:ABCDEFB0123456789
    //    :00X:ABCDEFB0123456789
    //    ...
    //    -}
    //    zusammenbauen

    TestStr := '{4:'+chr(13)+chr(10);

    for l1 := 1 to 500 do
        TestStr := TestStr + ':00X:ABCDEFB0123456789' +chr(13)+chr(10);

    TestStr := TestStr + '-}';


    re.Subject := TestStr;

    re.Match;

    { TODO -oUser -cConsole Main : Code hier einfügen }
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;

  ReadLn;
end.
Es knallt bei re.match.

Angehängt ist auch ein Beipielprojekt. Ist hoffentlich so korrekt. Delphi XE ist übrigens die Enterprise-Edition.

TRegExErr.zip
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 23:10 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 by Thomas Breitkreuz