Solved

multi-thread application

Posted on 2004-10-05
12
382 Views
Last Modified: 2010-08-05
When trying to execute a multi-thread application in Delphi 6, it gives an error with message:
faulted with message: access violation at 0x005517e8: write of address 0x38010b12. Process stopped.
What does this error mean? How can I solve this situation
0
Comment
Question by:MauricioGaviria
  • 4
  • 4
  • 2
  • +2
12 Comments
 
LVL 6

Expert Comment

by:david_barker
ID: 12229637
I think you are going to have to give more details, like where the code breaks.
0
 

Author Comment

by:MauricioGaviria
ID: 12230528
ok
this is the source
------------------------------------------------------------------------------------------------------------------------------------------------
main Unit
------------------------------------------------------------------------------------------------------------------------------------------------
unit main;
interface
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ComCtrls;
type
  TserverGui = class(TForm)
    PageControl1: TPageControl;
    TabSheet1: TTabSheet;
    TabSheet2: TTabSheet;
    Button1: TButton;
    RichEdit1: TRichEdit;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
    ThreadsRunning: Integer;
    procedure iniciarCopiaArchivo(listaEquipos:TStringList;idCmd:String);
    procedure FOnDoneParsing(Sender: TObject);

  public
    { Public declarations }
  end;

var
  serverGui: TserverGui;

implementation

uses hiloArchivo;

{$R *.dfm}

procedure TserverGui.Button1Click(Sender: TObject);
var
    listaEquipos : TStringList;
    idComando : String;
begin
    listaEquipos.Add('pp');
    listaEquipos.Add('pp2');
    listaEquipos.Add('pp3');
    listaEquipos.Add('pp4');
    listaEquipos.Add('pp5');
    listaEquipos.Add('pp6');
    listaEquipos.Add('pp7');
    listaEquipos.Add('pp8');
    listaEquipos.Add('pp9');
    listaEquipos.Add('pp10');
    listaEquipos.Add('pp11');
    listaEquipos.Add('pp12');
    listaEquipos.Add('pp13');
    iniciarCopiaArchivo(listaEquipos,'540');
end;

procedure TServerGui.iniciarCopiaArchivo(listaEquipos:TStringList;idCmd:String);
begin
    ThreadsRunning := 1;
    with TEscribirArchivo.Create(listaEquipos, idCmd) do
         OnTerminate := FOnDoneParsing;
    Button1.Enabled := False;
end;

procedure TServerGui.FOnDoneParsing(Sender: TObject);
begin
  Dec(ThreadsRunning);
  if ThreadsRunning = 0 then
  begin
    Button1.Enabled := True;
  end;
end;
end.
------------------------------------------------------------------------------------------------------------------------------------------------
unit thread
------------------------------------------------------------------------------------------------------------------------------------------------
unit hiloArchivo;

interface

uses
  Classes;

type
  ThiloEscrituraArchivo = class(TThread)
  private
    { Private declarations }
    listaEqps : TStringList;
    idComando : String;
  protected
    procedure Execute; override;
    procedure mostrarProgreso;
    procedure escribir_a_Archivo(listaPCs:TStringList;idComandoExe:String); virtual; abstract;
  public
    constructor Create(lista: TStringList; idCmd: String);
  end;

  TEscribirArchivo = class(ThiloEscrituraArchivo)
  protected
    procedure escribir_a_Archivo(listaPCs:TStringList;idComandoExe:String);
  end;
implementation
uses excaliburAdminCode;
{ Important: Methods and properties of objects in VCL or CLX can only be used
  in a method called using Synchronize, for example,

      Synchronize(UpdateCaption);

  and UpdateCaption could look like,

    procedure hiloEscrituraArchivo.UpdateCaption;
    begin
      Form1.Caption := 'Updated in a thread';
    end; }

{ hiloEscrituraArchivo }
constructor ThiloEscrituraArchivo.Create(lista: TStringList; idCmd: String);
begin
    listaEqps := TStringList.Create;
    listaEqps := lista;
    idComando := idCmd;
    FreeOnTerminate := True;
    inherited Create(False);
end;
procedure ThiloEscrituraArchivo.Execute;
begin
    { Place thread code here }
    escribir_a_Archivo(listaEqps,idComando);
end;
procedure ThiloEscrituraArchivo.mostrarProgreso;
begin
    serverGui.RichEdit1.Lines.Add('ok');
    serverGui.RichEdit1.Lines.Add(listaEqps.Strings[0]);
end;
procedure TEscribirArchivo.escribir_a_Archivo(listaPCs:TStringList;idComandoExe:String);
begin
    listaPCs.SaveToFile('comandos.txt');
    Synchronize(mostrarProgreso);
end;
end.
0
 
LVL 17

Expert Comment

by:Wim ten Brink
ID: 12230538
It means that on address 0x005517e8 there's a function trying to either read or write data on address 0x38010b12. However, this memory address is protected for some reason and the action cannot be executed. You don't have access, thus you get an access violation.
If you want to get a more detailed answer, please give more details about your application. ;-)

It is most likely that some component or object or function is trying to access something in one thread that has been freed in the other thread. You could try debugging the code but it's better to write log information to a log file.
0
Windows Server 2016: All you need to know

Learn about Hyper-V features that increase functionality and usability of Microsoft Windows Server 2016. Also, throughout this eBook, you’ll find some basic PowerShell examples that will help you leverage the scripts in your environments!

 
LVL 13

Expert Comment

by:BlackTigerX
ID: 12230610
the problem might be because you are passing a reference to all threads to that list

try something like this:

procedure TServerGui.iniciarCopiaArchivo(listaEquipos:TStringList;idCmd:String);
begin
    ThreadsRunning := 1;
    with TEscribirArchivo.Create(listaEquipos, idCmd) do
    begin
         OnTerminate := FOnDoneParsing;
         Sleep(20) //just give time for this thread to assign that list to its internal list
    end;
    Button1.Enabled := False;
end;
0
 
LVL 6

Accepted Solution

by:
vadim_ti earned 500 total points
ID: 12232798
Hi, I think you need to do 2 changes:

1) in procedure Button1Click you need to create TStringList

listaEquipos := TStringList.Create;

before adding items

2) in constructor

ThiloEscrituraArchivo

instead of
 listaEqps := lista;

have to be
   listaEqps.AddStrings(lista);
0
 
LVL 17

Expert Comment

by:Wim ten Brink
ID: 12235451
One simple advise, which not many people follow anyway: Don't use your native language for class names, variable names and anything else. Try using English names for them. Not that it matters much, but when you need help from people like us at EE who don't understand your native language, your code snippets become a bit easier to read. It also helps if you ever plan to sell the sourcecode to some other party. But as I said, not many people do this anyway.

vadim_ti is right. Use listaEqps.AddStrings(lista);

But the real flaw is here:
constructor ThiloEscrituraArchivo.Create(lista: TStringList; idCmd: String);
begin
    listaEqps := TStringList.Create;
    listaEqps := lista;
    idComando := idCmd;
    FreeOnTerminate := True;
    inherited Create(False);
end;

Should be:
constructor ThiloEscrituraArchivo.Create(lista: TStringList; idCmd: String);
begin
    inherited Create(False);
    listaEqps := TStringList.Create;
    listaEqps := lista;
    idComando := idCmd;
    FreeOnTerminate := True;
end;

0
 
LVL 6

Expert Comment

by:vadim_ti
ID: 12235506
Alex:

i do not think you are right, must be:

constructor ThiloEscrituraArchivo.Create(lista: TStringList; idCmd: String);
begin
    listaEqps := TStringList.Create;
    listaEqps.AddStrings(lista);           // <==
    idComando := idCmd;
    FreeOnTerminate := True;
    inherited Create(False);
end;

please tell me what a difference where you place
   inherited Create;
i do not understand
0
 

Author Comment

by:MauricioGaviria
ID: 12238736
thanks a lot
0
 
LVL 17

Expert Comment

by:Wim ten Brink
ID: 12243682
@vadim_ti, you are wrong... You must FIRST call the inherited Create, then initialize whatever you want to be initialized. If you do it the other way around, you risk that the inherited create will clear some of the data you've just initialized. With destructors, you call the inherited method as last method, but with constructors you MUST call the inherited create first.

Because, do you realise that the default behaviour of TObject.Create is to zero the memory used by the component? It checks the size, then cleans it. Thus if you've added some data in it... Well, you know the risk.

The constructor initializes the data, thus you first want to call the inherited stuff, so that part is correctly initialized, then add your own stuff. With destructors it's the other way around, cleaning your stuff first before the inherited destructor gets the chance to clean the rest.

In most cases I just do this:

constructor ThiloEscrituraArchivo.Create(lista: TStringList; idCmd: String);
begin
    inherited Create(TRUE); // Create it suspended.
    listaEqps := TStringList.Create;
    listaEqps.AddStrings(lista);           // <==
    idComando := idCmd;
    FreeOnTerminate := True;
    RESUME; // Resume the thread.
end;
0
 
LVL 6

Expert Comment

by:vadim_ti
ID: 12244206
ok, i regular do the same, but in this case, there are no difference

below is thread constructor with my comments

constructor TThread.Create(CreateSuspended: Boolean);
begin
  inherited Create;                                // do nothing (TObject constructor)
  AddThread;                                       // add thread to threads list
  FSuspended := CreateSuspended;      // it is ok
  FCreateSuspended := CreateSuspended; // it is ok
// we do not use thread  handle
  FHandle := BeginThread(nil, 0, @ThreadProc, Pointer(Self), CREATE_SUSPENDED, FThreadID);
  if FHandle = 0 then
    raise EThread.CreateResFmt(@SThreadCreateError, [SysErrorMessage(GetLastError)]);
end;

what i wanted to say , in this case there is no difference where you call inherited constructor.
i even checked 2 cases to be sure.

i do not understand one thing, why FreeOnTerminate works with this constructor:

constructor ThiloEscrituraArchivo.Create(lista: TStringList; idCmd: String);
begin
    listaEqps := TStringList.Create;
    listaEqps := lista;
    idComando := idCmd;
    FreeOnTerminate := True;
    inherited Create(False);
end;

0
 
LVL 17

Expert Comment

by:Wim ten Brink
ID: 12247342
The TObject.Create isn't doing nothing! At least not with all Delphi versions. The fact that it just happens to work this time isn't really professional, though. That's just my main objection with that method of calling the inherited method as last one. The reason that FreeOnTerminate just happens to work is probably because it is not cleared in the inherited create methods. Basically, that's a bug because it means it could contain any kind of value.

All I'm saying is that you cannot rely that it continues to work with the next Delphi version.
0
 
LVL 6

Expert Comment

by:vadim_ti
ID: 12247613
thanks
0

Featured Post

3 Use Cases for Connected Systems

Our Dev teams are like yours. They’re continually cranking out code for new features/bugs fixes, testing, deploying, testing some more, responding to production monitoring events and more. It’s complex. So, we thought you’d like to see what’s working for us.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
In my programming career I have only very rarely run into situations where operator overloading would be of any use in my work.  Normally those situations involved math with either overly large numbers (hundreds of thousands of digits or accuracy re…
With Secure Portal Encryption, the recipient is sent a link to their email address directing them to the email laundry delivery page. From there, the recipient will be required to enter a user name and password to enter the page. Once the recipient …
A short tutorial showing how to set up an email signature in Outlook on the Web (previously known as OWA). For free email signatures designs, visit https://www.mail-signatures.com/articles/signature-templates/?sts=6651 If you want to manage em…

803 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question