Delphi-PRAXiS
Seite 1 von 2  1 2      

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... :)


Alle Zeitangaben in WEZ +1. Es ist jetzt 07:12 Uhr.
Seite 1 von 2  1 2      

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