Search code examples
lazarusfreepascalsegmentation-fault

Pascal: Project raising External: SIGSEGV when interacting with Form


Let's say, there are 3 forms in a project (Form1, Form2, Form3). Form1 has a button on it with the OnClick event set to Form2.Show. This code executes perfectly, however if Form2's code tries to call Form3.Show, then the project raises an EXTERNAL: SIGSEGV pointing to Customform.inc

Project project1 raised exception class 'External: SIGSEGV'

In file '.\include\customform.inc' at line 2196:

Visible := True;

This is exactly what's happening to my project. All forms were properly created and declared, and the units are linked perfectly. The compilation goes fine, without any errors or warnings.

So it is impossible to make the third form visible. But I've discovered that every kind of interaction would result in an External: SIGSEGV error pointing to random pieces of code which compile and run just fine. I just can't figure out the origin of the error.

If I try to execute my project without the debugger, I get an Access Violation error. Failing code:

procedure TWarForm.FormCreate(Sender: TObject);
Begin
   Form3.Show;
end;

from

unit work;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls,
  StdCtrls, BGRAFlashProgressBar, AuthUnit;

type

  { TWarForm }

  TWarForm = class(TForm)
    ArcaneDustIMG: TImage;
    ProgressBar: TBGRAFlashProgressBar;
    ArcaneEDT: TEdit;
    GoldEDT: TEdit;
    GoldIMG: TImage;
    Label1: TLabel;
    Wallpaper: TImage;
    procedure FormCreate(Sender: TObject);
    procedure WallpaperMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure WallpaperMouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure WallpaperMouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
  private
    { private declarations }
  public
    { public declarations }
  end;

var
  WarForm: TWarForm;
  MouseIsDown: Boolean;
  PX, PY: Integer;

implementation

{$R *.lfm}

{ TWarForm }

procedure TWarForm.WallpaperMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  if Button = mbLeft then begin
    MouseIsDown := True;
    PX := X;
    PY := Y;
  end;
end;

procedure TWarForm.FormCreate(Sender: TObject);
Begin
   Form3.Show;
end;

procedure TWarForm.WallpaperMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
  if MouseIsDown then begin
    SetBounds(WarForm.Left + (X - PX), WarForm.Top + (Y - PY), WarForm.Width, WarForm.Height);
  end;
end;

procedure TWarForm.WallpaperMouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  MouseIsDown:=False;
end;

end.
   

Solution

  • You have to create the forms either manualy or set them to "auto create" in your IDE

    To Create them manualy just change your code slightly:

     TWarForm = class(TForm)
        ArcaneDustIMG: TImage;
        ProgressBar: TBGRAFlashProgressBar;
        ArcaneEDT: TEdit;
        GoldEDT: TEdit;
        GoldIMG: TImage;
        Label1: TLabel;
        Wallpaper: TImage;
    
        Form2: TForm2; // insert Form2
        Form3: TForm3; // and Form3
    
        procedure FormCreate(Sender: TObject);
        procedure WallpaperMouseDown(Sender: TObject; Button: TMouseButton;
          Shift: TShiftState; X, Y: Integer);
        procedure WallpaperMouseMove(Sender: TObject; Shift: TShiftState; X,
          Y: Integer);
        procedure WallpaperMouseUp(Sender: TObject; Button: TMouseButton;
          Shift: TShiftState; X, Y: Integer);
      private
        { private declarations }
      public
        { public declarations }
      end;
    
      ..
    
      procedure TWarForm.FormCreate(Sender: TObject);
      Begin
        Form3 := TForm3.Create(Self);
        Form3.Show;
      end;    
    

    If you do so, don't forget to call Form3.Free at the end of your application execution.