Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Alt -> Stacküberlauf (https://www.delphipraxis.net/152670-alt-stackueberlauf.html)

blablab 1. Jul 2010 11:44

Alt -> Stacküberlauf
 
Hallo!

Ich habe einen wirklich merkwürdigen Fehler. Ich hab eine Komponente programmiert und wenn ich diese in ein Projekt mache und "Alt" drücke, dann gibt es einen Stack-Überlauf. Dabei muss meine Komponente nicht einmal den Fokus haben. Wenn man zum Beispiel gerade in einem Memo arbeitet und zufällig Alt drückt, stürzt das Programm ab.
Um den Fehler zu suchen hab ich in allen von mir programmierten Methoden Haltepunkte gesetzt, allerdings wird beim Stacküberlauf keine von denen aufgerufen. Deshalb steh ich jetzt aufm Schlauch und weiß nicht wo ich suchen soll.

Ich erwarte von euch keine Wunder, aber weiß jemand wo ich suchen könnte, hatte jemand schon ein ähnliches Problem oder habt ihr irgendwelche anderen Ideen???

Würde mich echt freuen :-D

Grüße
blablab

blackfin 1. Jul 2010 11:53

AW: Alt -> Stacküberlauf
 
Irgendeine falsche Rekursion (Funktion ruft sich immer wieder selbst auf) in einem MainMenu-Eintrag drin, sobald der ausgewählt wird?
Stack Overflow passiert gewöhnlich meist dann, wenn sich eine Funktion immer wieder selbst aufruft.

SirThornberry 1. Jul 2010 11:54

AW: Alt -> Stacküberlauf
 
Was zeigt denn der Stackcall an? Und welche Delphiversion hast du? Ich kann mich dunkel daran erinnern das dies ein Bug war/ist der sich glaub ich im Mainmenü verstekct hat.

blablab 1. Jul 2010 12:24

AW: Alt -> Stacküberlauf
 
Ich benutze Delphi7. Ein MainMenu hab ich im Projekt nicht. Der Fehler tritt auch auf wenn ich ein leeres Projekt nur mit meiner Komponente habe.

Ich hab jetzt rausgefunden welche Methode sich immer wieder selbst aufruft:

Delphi-Quellcode:
procedure TWinControl.WMSysCommand(var Message: TWMSysCommand);
var
  Form: TCustomForm;

  function TraverseControls(Container: TWinControl): Boolean;
  var
    I: Integer;
    Control: TControl;
  begin
    Result := False;
    if Container.Showing then
      for I := 0 to Container.ControlCount - 1 do
      begin
        Control := Container.Controls[I];
        if Control.Visible and Control.Enabled then
        begin
          if (csMenuEvents in Control.ControlStyle) and
            (Control.Perform(WM_SYSCOMMAND, TMessage(Message).WParam,
              TMessage(Message).LParam) <> 0) or (Control is TWinControl) and
            TraverseControls(TWinControl(Control)) then
          begin
            Result := True;
            Exit;
          end;
        end;
      end;
  end;

begin
  with Message do
  begin
    if (CmdType and $FFF0 = SC_KEYMENU) and (Key <> VK_SPACE) and
      (Key <> Word('-')) and not IsIconic(FHandle) and (GetCapture = 0) and
      (Application.MainForm <> Self) then
    begin
      Form := GetParentForm(Self);
{y}   if (Form <> nil) and (Form.Perform(CM_APPSYSCOMMAND, 0, Longint(@Message)) <> 0) then
        Exit;
    end;
    { Broadcast WMSysCommand to all controls which have a csMenuEvents style. }
{x}   if (CmdType and $FFF0 = SC_KEYMENU) and TraverseControls(Self) then
      Exit;
  end;
  inherited;
end;
Es wechselt immer wieder zwischen Zeile {x} und {y} hin und her bis zum Stacküberlauf.

P.S. Stackcall??? :stupid:

himitsu 1. Jul 2010 12:29

AW: Alt -> Stacküberlauf
 
Zitat:

Zitat von blackfin (Beitrag 1032803)
Irgendeine falsche Rekursion ...

Nein, nicht nur.
Ein Stacküberlauf kommt, wenn der Speicher dafür ausgeht.
Praktisch das OutOfMemory des Stacks.

Der Stack wird z.B. durch lokale Variaben, Funktionsaufrufe (Rücksprungadresse) und Dergleichen gefüllt.

also:
- zuviele rekursive Funktionsaufrufe
und/oder
- zu viele/große lokale Variablen (welche im Stack liegen)

blablab 1. Jul 2010 12:34

AW: Alt -> Stacküberlauf
 
Er ruft sich hier immer wieder (indirekt) selbst auf, bei jedem aufruf speichert er sich ein paar lokale Variablen im Stack und irgendwann ist der Stack voll...

Delphi-Quellcode:
procedure TWinControl.WMSysCommand(var Message: TWMSysCommand);
var
  Form: TCustomForm;

  function TraverseControls(Container: TWinControl): Boolean;
  var
    I: Integer;
    Control: TControl;
  begin
{3} Result := False;
    if Container.Showing then
      for I := 0 to Container.ControlCount - 1 do
      begin
        Control := Container.Controls[I];
        if Control.Visible and Control.Enabled then
        begin
          if (csMenuEvents in Control.ControlStyle) and
{4}         (Control.Perform(WM_SYSCOMMAND, TMessage(Message).WParam,
              TMessage(Message).LParam) <> 0) or (Control is TWinControl) and
            TraverseControls(TWinControl(Control)) then
          begin
            Result := True;
            Exit;
          end;
        end;
      end;
  end;

begin
  with Message do
  begin
{1}{5}if (CmdType and $FFF0 = SC_KEYMENU) and (Key <> VK_SPACE) and
      (Key <> Word('-')) and not IsIconic(FHandle) and (GetCapture = 0) and
      (Application.MainForm <> Self) then
    begin
      Form := GetParentForm(Self);
      if (Form <> nil) and
{6}     (Form.Perform(CM_APPSYSCOMMAND, 0, Longint(@Message)) <> 0) then
        Exit;
    end;
    { Broadcast WMSysCommand to all controls which have a csMenuEvents style. }
{2} if (CmdType and $FFF0 = SC_KEYMENU) and TraverseControls(Self) then
      Exit;
  end;
  inherited;
end;

procedure TCustomForm.CMAppSysCommand(var Message: TMessage);
type
  PWMSysCommand = ^TWMSysCommand;
begin
  Message.Result := 0;
  if (csDesigning in ComponentState) or (FormStyle = fsMDIChild) or
   (Menu = nil) or Menu.AutoMerge then
    with PWMSysCommand(Message.lParam)^ do
    begin
      SendCancelMode(nil);
{7}   if SendAppMessage(CM_APPSYSCOMMAND, CmdType, Key) <> 0 then
        Message.Result := 1;;
    end;
end;

procedure TApplication.WndProc(var Message: TMessage);
...
begin
...
    with Message do
      case Msg of
...
        CM_APPSYSCOMMAND:
          if MainForm <> nil then
            with MainForm do
              if (Handle <> 0) and IsWindowEnabled(Handle) and
                IsWindowVisible(Handle) then
              begin
                FocusMessages := False;
                SaveFocus := GetFocus;
                Windows.SetFocus(Handle);
{8}             Perform(WM_SYSCOMMAND, WParam, LParam);
                Windows.SetFocus(SaveFocus);
                FocusMessages := True;
                Result := 1;
              end;
...
end;
Es geht immer {1}...{8}{1}...{8}{1}...

Jetzt muss ich nurnoch verstehen was er da macht und was ich falsch gemacht habe...

himitsu 1. Jul 2010 12:40

AW: Alt -> Stacküberlauf
 
Wo kommt denn der Post plötzlich her :shock:

Du sendest WM_SYSCOMMAND und CM_APPSYSCOMMAND innerhalb der Funktion (WMSysCommand), welche diese Nachrichten auch verarbeitet ... endlosschleife

Kennst du den PingPong-Witz?
Scheibe links an die Klowand "Magst du Tennis, dann schau nach rechts"
und rechts kommt "Magst du Tennis, dann schau nach links" dran.

blablab 1. Jul 2010 12:49

AW: Alt -> Stacküberlauf
 
Das ist ja nicht von mir, das ist ja der Delphi-Code...


Ich könnte versuchen [csMenuEvents] aus dem ControlStyle meiner Komponente herauszunehmen. In der Hilfe steht dazu "Das Steuerelement reagiert auf Befehle des Steuerungsmenüs." Was bedeutet das??? :stupid:

blablab 1. Jul 2010 13:16

AW: Alt -> Stacküberlauf
 
Ich hab jetzt [csMenuEvents] aus dem ControlStyle meiner Komponente herausgenommen. Dadurch gibts kein Stack-Überlauf mehr da Schritt {4} nicht mehr aufgerufen wird. Eigentlich änder ich ja nicht so gern einfach iwelche Eigenschaften ohne es wirklich zu verstehn was ich da mache. Aber dadurch geht der Fehler weg und anscheinend gehen keine Funktionen meiner Komponente verloren. Also was soll's :-D

Danke für eure Hilfe!

blackfin 1. Jul 2010 13:42

AW: Alt -> Stacküberlauf
 
Zitat:

Eigentlich änder ich ja nicht so gern einfach iwelche Eigenschaften ohne es wirklich zu verstehn was ich da mache. Aber dadurch geht der Fehler weg und anscheinend gehen keine Funktionen meiner Komponente verloren
Das würde mir aber trotzdem zu Denken geben bzw. zumindest ein ganz übles Bauchgefühl hinterlassen, wenn so ein Programm dann irgendwann mal an einen Kunden ausgeliefert werden soll... :)

blablab 2. Aug 2010 16:20

AW: Alt -> Stacküberlauf
 
Etwas spät aber:

Ich finde das sollte den Delphi-Programmieren zu denken geben, den immerhin tritt der Stacküberlauf ja nicht in meinem sondern in deren Code auf :-D

himitsu 2. Aug 2010 16:23

AW: Alt -> Stacküberlauf
 
Das muß aber nicht bedeuten, daß der Ursache dafür nicht doch bei dir liegt.

Wenn ich den Busfahrer ablenke/erschlage, dann liegt der Fehler (Unfall) nicht beim Hersteller des Busses.

DeddyH 2. Aug 2010 16:35

AW: Alt -> Stacküberlauf
 
[OT]
Zitat:

Zitat von himitsu (Beitrag 1039035)
Das muß aber nicht bedeuten, daß der Ursache dafür nicht doch bei dir liegt.

Wenn ich den Busfahrer ablenke/erschlage, dann liegt der Fehler (Unfall) nicht beim Hersteller des Busses.

Wenn Du in den USA klagst, könntest Du aber damit durchkommen :mrgreen: [/OT]

mkinzler 2. Aug 2010 18:11

AW: Alt -> Stacküberlauf
 
Aber nur, wenn der Hersteller dies nicht ausdrücklich in seinem AGBs ausschliesst.

blablab 3. Aug 2010 08:56

AW: Alt -> Stacküberlauf
 
Ja gut, das stimmt schon. In irgendeiner Weise hab ich den Fehler natürlich selbst verursacht.
(Hätte ich meinen PC gar nicht erst angeschaltet, wäre es nicht zu dem Fehler gekommen :) )

Aber ich bin der Meinung, dass Delphi bei der falschen Verwendung mit einem Fehler reagieren sollte und nicht mit einem undurchsichtigen Stack-Überlauf.

Das Beispiel sollte aber eher so lauten: Ich setze mich im Bus mit dem Kopf nach unten auf einen Sitz -> Bus kaputt. :-D

himitsu 3. Aug 2010 09:19

AW: Alt -> Stacküberlauf
 
Zitat:

Zitat von blablab (Beitrag 1039179)
Aber ich bin der Meinung, dass Delphi bei der falschen Verwendung mit einem Fehler reagieren sollte und nicht mit einem undurchsichtigen Stack-Überlauf.

Es ist aber "leider" nicht möglich auf alle möglichen Fehler angemessen zu reagieren.
Denn dann wären 99,9% in Delphi nur noch Fehlererkennungscode und alle würden sich über die mindestens 200 MB einer leeren Anwendung aufregen :zwinker:

blablab 3. Aug 2010 09:56

AW: Alt -> Stacküberlauf
 
Wirklich? Seit ich Delphi programmiere war ich bis jetzt immer zufrieden mit der Fehlererkennung. Das ist der erste Fehler mit dem ich nicht zufrieden bin. Ich kann mir einfach nicht vorstellen dass es noch so viele derartige Fehler in Delphi gibt, falls es überhaupt noch welche gibt...

Bernhard Geyer 3. Aug 2010 09:59

AW: Alt -> Stacküberlauf
 
Zitat:

Zitat von blablab (Beitrag 1039200)
..., falls es überhaupt noch welche gibt...

Gehe davon aus das es noch sehr viele sind. Hab selbst vor kurzen welche gefunden welche erst unter Win7 zu tragen kommen

blablab 3. Aug 2010 10:03

AW: Alt -> Stacküberlauf
 
ohje. auf einen solchen Fehler zu stoßen find ich ja nicht so schlimm. Aber wenn du gleich auf mehrere stößt muss das ziemlich viel Arbeit und nervig sein...

himitsu 3. Aug 2010 10:09

AW: Alt -> Stacküberlauf
 
Vorallem in den Generics, den Record-Methoden und ähnlichen Dingen verstecken sich leider viele Compilerfehler, auf welche ich auch schon gestoßen bin. :(
Ich sagte ja nicht, daß nicht Vieles erkannt und auch benannt wird, aber "alles" geht einfach nicht
und insgesamt ist wird halt dennoch nur ein winziger Teil erkannt/behandelt, auch wenn es im Vergleich zu einigen anderen Sprachen auch schon viel sein mag.


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