![]() |
Erhalte vom Programm "Keine Rückmeldung" - Speicherüberlauf?
Hallo Gemeinde,
ich habe wieder mal ein Problem(chen) und hoffe auf Hilfe. Zur Ausgangssituation: Ich habe einen String mit bis zu 1000 Zeichen, den ich in einer Funktion bearbeiten möchte. Diese Funktion dient dazu den Text auf eine bestimmte Breite zu bringen (60 Zeichen). Weiterhin habe ich meiner Funktion beigebracht, dass der Test um 15 Zeichen eingerückt werden soll. Meine Funktion setzt auch brav den Zeilenumbruch (#13#10) an letzten Leerzeichen bevor die Zeilenbreite von 60 erreicht ist und rückt den Text ein - Zeile für Zeile. Anschließend übernehme ich den nun "neuen" String mit den Zeilenumbrüchen in die Zwischenablage. Zum Problem: Wenn ich nun eine Weile an meinen PC arbeite und einige Programme offen habe, erhalte ich irgendwann, wenn ich meine Funktion nutze, die Meldung des Programms (in dem meine Funktion agiert): "Keine Rückmeldung" Ich kann dann nur noch das Programm schließen und neu starten. Aber auch dann bekomme ich immer wieder diese Meldung. Starte ich aber meinen Rechner neu, ist das Problem erst mal wieder verschoben. Nun habe ich mich etwas belesen und dabei festgestellt "Text := Text + WeitererText" sehr schnell den Arbeitsspeicher füllen kann. Da ich eine WHILE-Schleife verwende, kann es je nach Textlänge passieren, dass diese Variable vielfach im Speicher abgelegt ist. Abhilfe hier soll der StringBuilder sein, der den String innerhalb einer Variable zusammen setzt und damit den (vermutlichen Speicherüberlauf) verhindert. Dies ist jedoch nicht der Fall. Darauf hin habe ich mir um der Sache auf den Grund zu kommen ein kleines Progrämmchen geschrieben, in dem ich in einer WHILE-Schleife einen Text X-mal hinter einen bestehenden anhänge, auf das Einrücken und Übernehmen des Strings in die Zwischenablage habe ich dabei noch verzichtet - Auch hier bekomme ich "Keine Rückmeldung". Dieses Progrämmchen habe ich einmal mit StringBuilder und einmal ohne, also "text := test + text" getestet. Meine Frage nun: Was genau habe ich übersehen, bzw. wie genau kann ich dieses vermutliche Speicherproblem umgehen? Wenn ich mich nicht verlesen habe ist eine Deklarierung der Variable mit "String" für 1000 Zeichen ausreichend, auch wenn ich noch einen Zeilenumbruch und den 15 Stellen Zeichenvorschub berücksichtige - oder? Hat jemand einen Tipp, wie ich das Problem beheben kann? Gerne kann ich einmal ein kurzes Beispiel der Funktion hier posten - sobald ich wieder Zuhause bin und an meinen Quelltext komme. Würde mich über eine Rückmeldung freuen. Liebe Grüße Micha Ps.: Verwende Delphi XE-XE4. Der Titel ist leider nicht sehr aussagekräftig, aber mir ist gerade nix besseres eingefallen |
AW: Erhalte vom Programm "Keine Rückmeldung" - Speicherüberlauf?
Erste Vermutung ist, die
Delphi-Quellcode:
Schleife ist endlos.
while
Da stimmt evtl etwas mit der Abbruchbedingung nicht. Ein Code Beispiel wir da bestimmt helfen. |
AW: Erhalte vom Programm "Keine Rückmeldung" - Speicherüberlauf?
Zitat:
|
AW: Erhalte vom Programm "Keine Rückmeldung" - Speicherüberlauf?
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo,
vielen Dank für Eure Rückmeldungen. Hier nun der Code.
Delphi-Quellcode:
Wie gesagt, das Programm funktioniert ja, nur wenn Windows ne Weile gelaufen ist und der Speicher vermutlich voll ist, dann kommt diese Meldung. Starte ich dann Rechner neu, kann ich wieder 2-4 Stunden damit arbeiten.
function Textumbruch(text: String; textbreite: Integer): String;
var textlaenge : Integer; zeilenlaenge : Integer; zwPos : Integer; zlPos : Integer; zu : String; orgText : String; kopText : String; ausgabetext : String; begin zu := #13#10; zwPos := 0; zlPos := 0; zeilenlaenge := 0; textlaenge := Length(text); orgText := text; kopText := text; while textlaenge > textbreite do begin zwPos := Pos(' ', kopText); zeilenlaenge := zeilenlaenge + zwPos; if zeilenlaenge > textbreite then begin ausgabetext := ausgabetext + Copy(orgText, 1, zlPos); ausgabetext := ausgabetext + zu; Delete(orgText, 1, zlPos); textlaenge := textlaenge - zlPos; zlPos := 0; zwPos := 0; zeilenlaenge := 0; end; zlPos := zlPos + zwPos; Delete(kopText, 1, zwPos); end; ausgabetext := ausgabetext + orgText; Result := ausgabetext; end; LG Micha (Hier mal das komplette Programm: Anhang 44192) |
AW: Erhalte vom Programm "Keine Rückmeldung" - Speicherüberlauf?
Ich habe den Algorithmus nicht durchschaut, aber er terminiert schon mal nicht wenn eine Zeile kein Leerzeichen vor der gewollten Textbreite hat. Er hängt dann an
Delphi-Quellcode:
nur immer weiter Zeilenumbrüche an bis der Speicher voll ist.
ausgabetext
PS: ![]() |
AW: Erhalte vom Programm "Keine Rückmeldung" - Speicherüberlauf?
@DieFliege: Eine winzige Kleinigkeit hast du übersehen.
Delphi-Quellcode:
Wenn nun kein Leerzeichen gefunden wird, welchen Wert hat dann wohl zwPos? Richtig: 0. Und genau da liegt der Hase im Pfeffer, denn du fragst niemals ab, ob das Leerzeichen auch gefunden wurde, was dann zu einer Endlosschleife führt. Nachstellen kannst du das, indem du mit dem gegebenen Text als Zeilenbreite einmal die 40 einstellst und dann die While-Schleife durchstepst.
zwPos := Pos(' ', kopText);
Beheben kannst du dieses unerwünschte Verhalten, indem du nach der Pos-Abfrage prüfst, ob zwPos > 0 ist. |
AW: Erhalte vom Programm "Keine Rückmeldung" - Speicherüberlauf?
Hallo Günther,
vielen Dank für Deine Rückmeldung. Du hast Recht, wenn kein Leerzeichen vor der Textbreite kommt, brummt das Programm auf. Da ich aber weiß, dass es keine Zeichenkombination geben wird, die länger als 50 oder gar 60 Zeichen geben wird, habe ich das mal außer acht gelassen. "WrapText" habe ich gerade kennen gelernt und beschäftige mich nun damit. Ich erkläre mal kurz, was ich mir bei der Funktion gedacht habe: Ich nutze eine WHILE-Schleife so lange, bis der Rest des Strings kleiner ist als die Textbreite. Dabei nutze ich 2 Strings mit anfänglich identischen Inhalt. Zunächst suche ich das erste Leerzeichen und übergebe die Position einer Variablen. nun lösche ich den text bis zum ersten Leerzeichen in der Kopie des Kopiestrings und suche nach den nächsten Leerzeichen. Die Position des neuen Leerzeichens kopiere ich zur letzten Position und prüfe ob damit die Textbreite überschritten wird. Wird sich überschritten, nutze ich die Gesamtpositionen aller Leerzeichen dazu, um vom Originaltext den Teil raus zu kopieren und in die Ergebnisstringvarible zu kopieren und lösche dann den kopieren Teil aus dem Originalstring. nun geht das ganze wieder von vorne los, bis der Rest des Kopiestrings kleiner ist als die Textbreite und dann endet die WHILE. Ich weiss, vermutlich ganz schön kompliziert - zu kompliziert, aber es funktioniert. Nutze ich nun statt "text := text + mehrtext" den StringBuilder, funktioniert es genauso und brummt bei ausgelastetem Rechner auf. So, werde nun WrapText" lernen ;-) LG Micha |
AW: Erhalte vom Programm "Keine Rückmeldung" - Speicherüberlauf?
Hallo Perlsau,
vielen Dank für den Hinweis. Das werde ich sofort mal umsetzen und mich danach (und dem Abendbrot) noch mal melden ;-) LG Micha :-) |
AW: Erhalte vom Programm "Keine Rückmeldung" - Speicherüberlauf?
Ach nochwas:
Statt
Delphi-Quellcode:
kannst Du besser
procedure TForm1.Button1Click(Sender: TObject);
begin memo2.Clear; memo2.SelLength := 0; quelltext := memo1.Text; textbreite := StrToInt(edit1.Text); memo2.SelText := Textumbruch(quelltext, textbreite); end;
Delphi-Quellcode:
das Clear / Sellength := 0 und SelText kannst Du dir sparen ;)
Memo2.Text := WrapText(StringReplace(Memo1.Text,#13#10,' ',[rfReplaceAll])
,sLineBreak , [' '] ,StrToInt(edit1.Text)); Ach ja, das StringReplace habe ich eingebaut, damit die in Memo1 vorhandenen Zeilenumbrüche nicht beim WrapText stören und sauber neu umgebrochen wird. |
AW: Erhalte vom Programm "Keine Rückmeldung" - Speicherüberlauf?
Und wo gibt er jetzt bei WrapText seine gewünschte Breite und Einrückung an?
|
AW: Erhalte vom Programm "Keine Rückmeldung" - Speicherüberlauf?
Delphi-Quellcode:
Memo2.Text := WrapText(StringReplace(Memo1.Text,#13#10,' ',[rfReplaceAll])
Ersetzt er damit nicht alle Leerzeichen mit einem Zeilenumbruch? @Lukie: Die Einrückung habe ich im "Progrämmchen" erst mal weg gelassen, um meinen Fehler zu finden ;-) So, ich habe nun nach Perlsau's Tipp meinen Quelltext angepasst:
Delphi-Quellcode:
Nun brummt das Programm bei der Einstellung nicht mehr auf.
while textlaenge > textbreite do
begin zwPos := Pos(' ', kopText); if zwPos > 0 then begin zeilenlaenge := zeilenlaenge + zwPos; if zeilenlaenge > textbreite then begin ausgabetext := ausgabetext + Copy(orgText, 1, zlPos); ausgabetext := ausgabetext + zu; Delete(orgText, 1, zlPos); textlaenge := textlaenge - zlPos; zlPos := 0; zwPos := 0; zeilenlaenge := 0; end else begin Break; end; zlPos := zlPos + zwPos; Delete(kopText, 1, zwPos); end; end; LG Micha |
AW: Erhalte vom Programm "Keine Rückmeldung" - Speicherüberlauf?
Nein,
![]()
Delphi-Quellcode:
StringReplace ersetzt im String S die Vorkommen des in OldPattern angegebenen Teilstrings durch den in NewPattern angegebenen Teilstring.
function StringReplace(const S, OldPattern, NewPattern: string; Flags: TReplaceFlags): string;
Was bedeutet "aufbrummen" in deinem Kontext? Bei mir hat da außer mir selbst nichts gebrummt. Zu deiner Programm-Änderung: zwPos = 0, wenn der Suchstring nicht gefunden wurde. Dann sind aber noch nicht zwangsläufig alle Wörter aus dem ersten Memo ins zweite übertragen, weil das ja innerhalb des neuen Begin-End-Blocks geschieht und dieser bei zwPos = 0 nicht mehr durchlaufen wird. Daher solltest du das nach Abarbeiten der While-Schleife noch überprüfen. Zum Fehlverhalten kam es, wenn ein Wort länger als die eingestellte Zeilenbreite ist, da kannst du verständlicherweise kein Leerzeichen finden. Es muß sich dabei nicht zwangsläufig um ein derart langes Wort handeln, denn auch falsche Zeichensetzung, z.B. das fehlende Leerzeichen nach Punkt oder Komme machen daraus programmtechnisch ein Wort. |
AW: Erhalte vom Programm "Keine Rückmeldung" - Speicherüberlauf?
Hallo Perlsau,
vielen Dank für Die Info zu "StringReplace" - Ich hab noch nicht nachgelesen was es genau bedeutet, nur eine Vermutung geäußert (Notiz an mich: Erst lesen, dann vermuten...) Vor der Abfrage, ob "zwPos > 0" ist, kam die Meldung "Keine Rückmeldung", nun erscheint diese nicht mehr - Dies meinte ich ;-) Danke für Deinen weiteren Hinweis, ich denke gerade drüber nach. LG Micha |
AW: Erhalte vom Programm "Keine Rückmeldung" - Speicherüberlauf?
Zitat:
Zitat:
|
AW: Erhalte vom Programm "Keine Rückmeldung" - Speicherüberlauf?
Zitat:
Hallo HolgerX, igit ist das einfach. Nun habe ich mir mal "WrapText" angesehen und auch Deinen Text verstanden. Vielen Dank allen, die mir auf die Sprünge geholfen haben. Wünsche Euch eine schöne Woche. LG Micha :-) Hallo Perlsau, Zitat:
Danke für Deine Hilfe, LG Micha :-) |
AW: Erhalte vom Programm "Keine Rückmeldung" - Speicherüberlauf?
Es kommt eben auf die Definition des Wortbegriffes an. Wenn du ein Wort so definierst, daß am Ende jeses Wortes ein Leerzeichen stehen muß, findest du natürlich nicht alle Worte, weil am Ende eines Satzes – zumindest im Deutschen – niemals ein Leerzeichen nach einem Wort steht, sondern gewöhnlich ein Punkt. Du willst aber gar nicht nach Worten suchen, sondern nach sinnvollen Stellen für den Textumbruch. Da ist das Leerzeichen natürlich vollkommen richtig gewählt – vorausgesetzt, daß derjenige, der den Text erfaßt, also getippt hat, sich an die deutsche Zeichensetzung hielt und auf jedes Satzzeichen ein Leerzeichen folgen ließ. Wenn der Text dagegen so aussieht:
Es kommt eben auf die Definition des Wortbegriffes an.Wenn du ein Wort so definierst,daß am Ende jeses Wortes ein Leerzeichen stehen muß,findest du natürlich nicht alle Worte,weil am Ende eines Satzes–zumindest im Deutschen–niemals ein Leerzeichen nach einem Wort steht,sondern gewöhnlich ein Punkt.Du willst aber gar nicht nach Worten suchen,sondern nach sinnvollen Stellen für den Textumbruch.Da ist das Leerzeichen natürlich vollkommen richtig gewählt–vorausgesetzt,daß derjenige,der den Text erfaßt,also getippt hat,sich an die deutsche Zeichensetzung hielt und auf jedes Satzzeichen ein Leerzeichen folgen ließ. In diesem Fall werden nicht alle Worte korrekt gefunden. Steht dann am Schluß des Textes noch ein Wort, das länger ist als die gewählte Textbreite, z.B. Rindfleischetikettierungsüberwachungsaufgabenübert ragungsgesetz, Grundstücksverkehrsgenehmigungszuständigkeitsübert ragungsverordnung, Verkehrsinfrastrukturfinanzierungsgesellschaftsges etz oder Vermögenszuordnungszuständigkeitsübertragungsveror dnung, wird dort auch kein Leerzeichen gefunden und das Wort wird nicht in das zweite Memo übernommen. Am besten scheint mir – so mache zumindest ich das immer bei komplexeren Aufgaben –, du stellst dir das Problem beim Debuggen bildlich vor oder malst es sogar erstmal genau auf, mit allen Eventualitäten. Bei Debuggen stelle ich mir bei jedem Programmschritt vor, wie die geänderte Variable danach auszusehen hat und schaue dann in den überwachten Ausdrücken nach, ob das erwartete Resultat auch eingetreten ist. Es ist ja letztlich die Aufgabe des Programmierers, nahezu alle denkbaren Eventualitäten abzudecken, um eine nahezu fehlerfreie Software zu garantieren. ![]() Leider zerstückelt der Foren-Editor die langen Wörter irgendwie ... |
AW: Erhalte vom Programm "Keine Rückmeldung" - Speicherüberlauf?
Um die Probleme etwas zu minimieren kannst Du auch den Aufruf von WrapText erweitern:
Delphi-Quellcode:
Oder Du gest hin und normalisierst den Text erstmal (z.B. Leerzeichen nach Satzzeichen einfügen..).
Memo2.Text := WrapText(StringReplace(Memo1.Text,#13#10,' ',[rfReplaceAll])
,sLineBreak , [' ','.',',','!','?',#9] // Hier alle Zeichen einfügen an denen umgebrochen werden kann ,StrToInt(edit1.Text)); Jedoch ist das mit WrapText einfacher ;) |
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:23 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