Recent

Author Topic: form1.free SIGSEGV  (Read 4973 times)

httpal

  • New Member
  • *
  • Posts: 14
form1.free SIGSEGV
« on: July 29, 2016, 04:02:09 am »
Hi!
There is the code:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.FormCreate(Sender: TObject);
  2. var
  3.   file_connect:TextFile;
  4.   file_string:string;
  5. begin
  6.   try
  7.      AssignFile(file_connect, GetCurrentDir + '/connect.ini');
  8.      Reset(file_connect);
  9.      Readln(file_connect, file_string);
  10.      CloseFile(file_connect);
  11.   Except
  12.      on E: exception do begin
  13.         ShowMessage('Error file "connection.ini"... '+#13+e.ClassName+#13+E.Message);
  14.         form1.Free;
  15.         //Application.Terminate;
  16.      end;
  17.   end;    
  18. end  
  19.  

and I get this message:
External: SIGSEGV

Lazarus 1.6, FPC 3.0 (32 bit)

Thanks in advance.

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: form1.free SIGSEGV
« Reply #1 on: July 29, 2016, 04:11:33 am »
Destroying/freeing an object inside itself is like driving a car at 200 mph and say let's remove (=free/destroy) the car (while passenger(s) continue the voyage)  :D
« Last Edit: July 29, 2016, 04:13:44 am by molly »

lainz

  • Hero Member
  • *****
  • Posts: 4468
    • https://lainz.github.io/
Re: form1.free SIGSEGV
« Reply #2 on: July 29, 2016, 04:26:53 am »
The real question here is what do you want to achieve?

Handoko

  • Hero Member
  • *****
  • Posts: 5154
  • My goal: build my own game engine using Lazarus
Re: form1.free SIGSEGV
« Reply #3 on: July 29, 2016, 05:11:28 am »
@httpal

OnCreate (FormCreate, etc) is a good place to put variable initialization. The code usually is short and fast. It is a bad practice to put heavy calculation, database access, file operation, freeing or destroying object code in there.

If the program you want to create is all automatic without user interaction (program start > do something automatically > quit), you may consider to choose non-GUI application: Lazarus main menu > File > New > Project.

Alternatively, if you still want to use GUI application to perform all automatic process. You may use TTImer: Program start > Enable TTimer > in TTimer.OnTimer event: if MainForm has finished loading then disable TTimer, perform the process and quit.
« Last Edit: July 29, 2016, 05:49:04 am by Handoko »

httpal

  • New Member
  • *
  • Posts: 14
Re: form1.free SIGSEGV
« Reply #4 on: August 01, 2016, 02:51:58 am »
Ok. What about Application.Terminate:
Code: Pascal  [Select][+][-]
  1.      on E: exception do begin
  2.         ShowMessage('Error file "connection.ini"... '+#13+e.ClassName+#13+E.Message);
  3.         Application.Terminate;
  4.      end;
  5.  
it does not work here...
The application is still running...

In another case it works:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.FormCreate(Sender: TObject);
  2. begin
  3.   try
  4.      MSSQLConnection1.Connected := true;
  5.   Except
  6.      on E: exception do begin
  7.         ShowMessage('Error connecting to DB... '+#13+e.ClassName+#13+E.Message);
  8.         Application.Terminate;
  9.      end;
  10.   end;
  11. end
  12.  
« Last Edit: August 01, 2016, 02:59:32 am by httpal »

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: form1.free SIGSEGV
« Reply #5 on: August 01, 2016, 03:55:28 am »
You seem to have put more weight to lainz' question (and the answer that belongs to it)  :)

May i be so bold as to ask why it is that you seem so determined to make things 'crash' before even opening a single form ? (bold assumption on the latter, but a reasonable one)

The only reason i can think of that makes your approach (somewhat) legit is if you really would like to perform such actions _before_ your main form has opened. And that you would like to refrain from showing a form all together when something did go wrong. If that should be the case, then please do like the rest of us do and add a module and let the designer create that module _before_ creating the main form.

In a module you can do all these kind of things and even instruct your application to not open the main form all together.

The simplest way of doing so (that i am aware of) is by removing the auto-creation of the form and add some code inside the module that creates and adds a (main)form manually to the application object and, doing so only when certain conditions have been met (conditions that you determine yourself).

If the application object has no forms to show at all, it will simply (and silently) exit (*).

In case you do not like the silent exit you could either show a messagebox or open a (dialog)form that explains the error/situation to the end-user.

Handoku's solution of using a timer is also legit, but depends a little on whether the actions you like to perform and/or data that needs to be retrieved can be done after the main form has shown itself or not.

The case of reading an ini file is a simple one. Just use a TIniFile but, also have default values hard-coded in your source so that in case the read of the .ini fails you are able to fall back to some default values. That way your oncreate handler does not have to terminate anything and can simply continue.

(*) seems you still need to do a manual terminate. Which is a simple: if "conditions tells us to create/show the form" then "Application.CreateForm(...)" else "terminate app".
« Last Edit: August 01, 2016, 05:07:29 am by molly »

Handoko

  • Hero Member
  • *****
  • Posts: 5154
  • My goal: build my own game engine using Lazarus
Re: form1.free SIGSEGV
« Reply #6 on: August 01, 2016, 05:38:32 am »
I guess httpal didn't fully understand what we have explained to him/her. Let's me try to explain using easier to understand words.

In the old days programming, the program flow is easier to understand because it runs straight from upper to lower (except looping, branching, sub routines/functions/procedures calling).

In nowadays, the flow is a bit harder to predict (for beginners) because the software (Lazarus, etc) is using event driven programming concept. What is it? Follow this link below if want to know more:
https://en.wikipedia.org/wiki/Event-driven_programming

httpal's code should be no problem if being used on non-event-driven programming. So, what's wrong? He/she failed to understand how event driven application works. The fix is not simply using free/terminate/halt/close or whatever to make the program stop.

Event driven programming is usually used for creating GUI applications. If you don't know what a GUI application is, in simple words, it is a program that has a mainform which usually has some buttons for users to click.

This is the simplified version how running normal GUI application will flow:

Quote
User run the program > initialize application data > initialize forms > forms' onCreate are processed > components' onCreate (in the form) are processed > displaying mainform > mainform's onActivate is processed > ...

This is the simplified version how running httpal's code will flow:

Quote
User run the program > initialize application data > initialize forms > forms' onCreate are processed > some process ... displaying showmessage ... quit > ...

Pay attention on the flow above. The form is just in the creation process and haven't fully created. In my opinion the name "FormCreate" event should be renamed as "FormBeforeCreation".

Because the form haven't 'really' created, you should not tell the program to quit or do some paintings (ShowMessage). As far as I know ShowMessage can only be used if the program has finished the loading process, that is in "mainform's onActivate".

So, what are the solutions if we want to make httpal's code works?

Solution1
Don't make it a GUI application. By doing so, it will become less event driven (it is still event driven actually).

Solution2
Using TTimer to make sure the mainform has fully loaded before processing the 'real' process.

Solution3
Follow molly's suggestion: disable form auto-creation and add some extra code. I haven't tried but it sounds possible. This Solution3 is a bit harder, I think. Similarly, I will suggest move httpal's code to the application main loop (in the *.lpr file).

Solution4
Add a button on the form and move the code to the button onClick event.

Solution5
I never tried, but it should work. Move the code to form's onActivate event (instead of FormCreate).

Solution6
Don't use ShowMessage. I'm not sure, but you can try. So remove the line that  has ShowMessage. To have ShowMessage running correctly, it requires the application to fully loaded.

Hope you can understand.
« Last Edit: August 01, 2016, 05:42:08 am by Handoko »

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: form1.free SIGSEGV
« Reply #7 on: August 01, 2016, 06:05:29 am »
That is very nice explanation of things Handoko  :-*

When doing this stuff for so long, one (as in me) tends to forget how hard it can be to go from simple procedural top-down flow to object oriented event driven flow.

Solution3
.... snip ... Similarly, I will suggest move httpal's code to the application main loop (in the *.lpr file).
fwiw: i explicitly haven't mentioned adjusting .lpr source as it seems code-tools get confused about it 9 out of 10 times especially when things become a bit more complicated with calling additional functions and conditional compilation :'(

Other than that, and depending on the circumstances/conditions it usually works as a good/quick solution. Single instance for example can be implemented in such a way and is imho much cleaner than dropping a component on a form.

Another possible approach might perhaps be to use the initialization section of a unit. But, quite frankly, i stopped using that myself as it gets confusing when having a couple of dozen units and you have to keep track of the correct order of things. One wrong ordered uses clause will for sure keep you busy debugging ...  :D

edit:
Demonstration of the described technique of using a data module is attached.

By default it does not do anything when fired (or so it acts). Add a .ini file with same name of the project (e.g. project1.ini) add a ini section named [options] and in there the keyword ShowForm with value 0 for not show or 1 for letting the application show the form.

The code itself perhaps makes no sense at all and is just there for demonstrating purpose. It's the used technique that is more interesting (hopfully)  :)
« Last Edit: August 01, 2016, 06:28:02 am by molly »

Handoko

  • Hero Member
  • *****
  • Posts: 5154
  • My goal: build my own game engine using Lazarus
Re: form1.free SIGSEGV
« Reply #8 on: August 01, 2016, 08:24:28 pm »
Yes, the DataModuleInit solution works. And it still works correctly if I add a ShowMessage command.

httpal

  • New Member
  • *
  • Posts: 14
Re: form1.free SIGSEGV
« Reply #9 on: August 02, 2016, 04:21:06 am »
Thanks for reply, I try to do it with before load Form program module. For me it's good solution. I initially went the wrong way.

Thanks!!!

 

TinyPortal © 2005-2018