Solved

multi-thread application

Posted on 2004-10-05
12
376 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
 
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
Threat Intelligence Starter Resources

Integrating threat intelligence can be challenging, and not all companies are ready. These resources can help you build awareness and prepare for defense.

 
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

Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

Join & Write a Comment

Introduction The parallel port is a very commonly known port, it was widely used to connect a printer to the PC, if you look at the back of your computer, for those who don't have newer computers, there will be a port with 25 pins and a small print…
Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
It is a freely distributed piece of software for such tasks as photo retouching, image composition and image authoring. It works on many operating systems, in many languages.
This video demonstrates how to create an example email signature rule for a department in a company using CodeTwo Exchange Rules. The signature will be inserted beneath users' latest emails in conversations and will be displayed in users' Sent Items…

743 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

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now