Access Violation On Create array of TThread

delphi, indy, multithreading

Solution

Your creation loop has 2 bugs in it:

1) You are looping to `High(Socks)-1` when you should be looping to `High(Socks)` instead. You are allocating arrays of 5 elements but only initializing 4 of them. Don't use -1 with `High()`, use it with `Length()` instead.

2) You are misusing `TSocks.Create()`, which is why you are getting an AV. You are calling it like an instance method instead of a constructor, but no instance has been constructed yet, thus the crash.

Use this instead:

For I := 0 To High(Socks) Do
Begin
  SA[I].SUrl := 'http://google.com.co';
  Socks[I] := TSocks.Create(SA[I]); // <-- here
  Socks[I].OnUpload := Self.OnUpload;
  Socks[I].Start;
End;

Problem

I am creating a multithreaded application, it creates a dynamic array of a class TThread, but the mystery for me, is that it causes an error 'Access Violation' to 'Create' Code Form: ``` Unit UNT_Main; Interface Uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, UNT_Socks; Type TFRM_Main = Class(TForm) Procedure FormCreate(Sender: TObject); Private Procedure OnUpload(Success: Boolean; SockAction: TSockAction); Public { Public declarations } End; Var FRM_Main: TFRM_Main; Socks: Array Of TSocks; SA: Array Of TSockAction; Implementation {$R *.dfm} Procedure TFRM_Main.OnUpload(Success: Boolean; SockAction: TSockAction); Begin ShowMessage(SockAction.Response); End; Procedure TFRM_Main.FormCreate(Sender: TObject); Var I: Integer; Begin SetLength(Socks, 5); SetLength(SA, 5); For I := 0 To High(Socks)-1 Do Begin SA[I].SUrl := 'http://google.com.co'; Socks[I].Create(SA[I]); Socks[I].OnUpload := Self.OnUpload; Socks[I].Start; End; End; End. ``` Code UNT_Socks: ``` Unit UNT_Socks; Interface Uses Classes, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient, IdHTTP; // action script Type TSockAction = Record SUrl: String; Response: String; End; // Eventos Type // on upload event TUpload = Procedure(Success: Boolean; SockAction: TSockAction) Of Object; // Clase Socks, ejecuta las acciones Type TSocks = Class(TThread) // Http indy sock Http: TIdHTTP; // action script FAtnSck: TSockAction; // Temp boolean response FbTempRet: Boolean; Private { Eventos } FOnUpload: TUpload; { Destructor } { Metodos & Funciones } Function UploadFile: Boolean; { Eventos } Procedure DoUpload; Protected Procedure Execute; Override; Public { Constructor } Constructor Create(SockAction: TSockAction); { Eventos } Property OnUpload: TUpload Read FOnUpload Write FOnUpload; End; Implementation { Constructor } Constructor TSocks.Create(SockAction: TSockAction); Begin Inherited Create(True); FAtnSck := SockAction; // <===== Access Violation Here! Http := TIdHTTP.Create(Nil); End; { Eventos } Procedure TSocks.DoUpload; Begin // check if the event is assign If Assigned(FOnUpload) Then // call it FOnUpload(FbTempRet, FAtnSck); End; { Execute } Procedure TSocks.Execute; Begin FbTempRet := UploadFile; Synchronize(DoUpload); End; Function TSocks.UploadFile: Boolean; Var SRes: String; Begin Try With Http Do FAtnSck.Response := Get(FAtnSck.SUrl); Except Result := False; End; Result := True; End; End. ``` What could be wrong? Thank you.

Original source