Watch, Follow, &
Connect with Us

For forums, blogs and more please visit our
Developer Tools Community.


Welcome, Guest
Guest Settings
Help

Thread: problem ntdll.dll?



Permlink Replies: 5 - Last Post: Aug 6, 2015 8:31 AM Last Post By: Peter Below
Lorenzo Crivell...

Posts: 4
Registered: 7/11/02
problem ntdll.dll?
Click to report abuse...   Click to reply to this thread Reply
  Posted: Aug 3, 2015 10:25 PM
Hello world,
i write my multithread application (xe6) that access at simultaneus websites , but i have random this error:

Exception class EAccessViolation with message 'Access violation at address 0000000000406B3E in module 'WebT.exe'. Read of address 0000001300000248'. Process WebT.exe (2456)

when I see the call stack I have this story

:000007fefda6b3dd
System.NotifyNonDelphiException(???,???)
System._DelphiExceptionHandler($12D9C0,1244192,$12D4D0,$12CE80)
:00000000779C91AD ; ntdll.dll
:00000000779B8BAF ; ntdll.dll
:00000000779EDB38 ; ntdll.dll
System.SysGetMem(???)
System._GetMem(???)
System._NewUnicodeString(172)
System.InternalUStrCatN('black reality teatro furio camillo ~~-~~ ~~~~~~ ~~~~ iv edizione l’associazione semivolanti, in collaborazione con l’archimandrita, presenterà a roma il progetto black… ',3,$12DC00 {' '})
System._UStrCatN('black reality teatro furio camillo ~~-~~ ~~~~~~ ~~~~ iv edizione l’associazione semivolanti, in collaborazione con l’archimandrita, presenterà a roma il progetto black… ',3)
AccessoWeb.CercaDateStg('black reality teatro furio camillo ~~-~~ ~~~~~~ ~~~~ iv edizione l’associazione semivolanti, in collaborazione con l’archimandrita, presenterà a roma il progetto black… ',32325)

the last row is the last instruction of my program:
if I clik on last line i have my last instruction that is simply:

OrigStg := Stg; //booth var are string format
or
Stg := StringReplace(Stg, Car, Canc, []);
or
............. (all times are strings operation)

but it change all times. The common stack call in all errors is this last part:

System.NotifyNonDelphiException(???,???)
System._DelphiExceptionHandler($12D8D0,1244192,$12D3E0,$12CD90)
:00000000779C91AD ; ntdll.dll
:00000000779B8BAF ; ntdll.dll
:00000000779EDB38 ; ntdll.dll
System.SysGetMem(???)

the problem is the ntdll.dll? can we help me...? i'm desperate!

tx
Lorenzo

Peter Below

Posts: 1,227
Registered: 12/16/99
Re: problem ntdll.dll?
Click to report abuse...   Click to reply to this thread Reply
  Posted: Aug 4, 2015 12:27 AM   in response to: Lorenzo Crivell... in response to: Lorenzo Crivell...
Lorenzo Crivellaro wrote:

Hello world,
i write my multithread application (xe6) that access at simultaneus
websites , but i have random this error:

Exception class EAccessViolation with message 'Access violation at
address 0000000000406B3E in module 'WebT.exe'. Read of address
0000001300000248'. Process WebT.exe (2456)

when I see the call stack I have this story

:000007fefda6b3dd
System.NotifyNonDelphiException(???,???)
System._DelphiExceptionHandler($12D9C0,1244192,$12D4D0,$12CE80)
:00000000779C91AD ; ntdll.dll
:00000000779B8BAF ; ntdll.dll
:00000000779EDB38 ; ntdll.dll

You can ignore that, that part of the call stack comes from the
exception processing.

System.SysGetMem(???)

That is the source of the exception. You said that you have a
multithreaded application. Are you using TThread descendents or a
different threading framework? Does the application use DLLs (other
than the system DLLs)?

If you use TThread descendents then the memory manager should be
automatically configure to operate in a thread-safe manner. But that
does not automatically make all operations done with compiler-managed
datatypes (like string) thread-safe! If you share string variables
between threads you still have to serialize access to them yourself, or
you may run into problems like the one you are having now...


--
Peter Below (TeamB)

Lorenzo Crivell...

Posts: 4
Registered: 7/11/02
Re: problem ntdll.dll?
Click to report abuse...   Click to reply to this thread Reply
  Posted: Aug 4, 2015 9:47 AM   in response to: Peter Below in response to: Peter Below

--
Peter Below (TeamB)

Hello,

Are you using TThread descendents or a different threading framework?
For multithread I use TThread descendents ( TMultiWeb = class(TThread) )

Does the application use DLLs (other than the system DLLs)?
No in this moment the application use only system dlls.

I use only a global integer variable to count the thread active... but if i cancel this var i have the same access violation problem,.. i post my multithread code (I hope can help to solve the problem):

constructor TMultiWeb.Create(Url: String; Mem: Boolean; Nom: String = ''; StTime: TDateTime = 0);
begin

inherited Create(False);
// Inc(ElabMultiWeb);
FUrl := TIdURI.URLEncode(Url);
FNom := Nom;
FMem := Mem;
FStTime := StTime;
Sito := '';
EndTime := 0;

//Se si vuole il sito in memoria deve essere fatto il free dal processo chiamante:
if (Mem) then
FreeOnTerminate := False
else
FreeOnTerminate := True;
end; {TMultiWeb.Create}

procedure TMultiWeb.Execute;
var
Web: TIdHTTP;
hIOHand: TIdSSLIOHandlerSocketOpenSSL;
begin
//Il Thread attende che venga raggiunta l'ora di esecuzione (se indicata):
while (Now < FStTime) do //or (ElabMultiWeb > MAX_MULTI_WEB) do
Application.ProcessMessages;

Web := TIdHTTP.Create(nil);
hIOHand := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
hIOHand.SSLOptions.Method := sslvTLSv1;
Web.IOHandler := hIOHand;
Web.HandleRedirects := True;

Web.Request.UserAgent := INET_USERAGENT; //Custom user agent string
Web.RedirectMaximum := INET_REDIRECT_MAX; //Maximum redirects
Web.HandleRedirects := INET_REDIRECT_MAX <> 0; //Handle redirects
Web.ReadTimeOut := INET_TIMEOUT_SECS * 1000; //Read timeout msec

try
Sito := Web.Get(FUrl); //Do the request
except
Sito := 'Errore accesso web';
end;

Web.Free;
hIOHand.Free;

if (not FMem) then
Synchronize(ScriviFile);

EndTime := Now;
// Dec(ElabMultiWeb);
end; {TMultiWeb.Execute}

and this is the class declaration:

TMultiWeb = class(TThread)
private
FUrl: String; //Inp: URl a cui accedere
FNom: String; //Inp: Nome del file da salvare (può contenete un numero o stringa significativa)
FMem: Boolean; //Inp: se True lavora in memoria, altrimenti scrive su file
FStTime: TDateTime; //Inp: giorno e ora di partenza per effettuare l'accesso all'url
procedure ScriviFile;
protected
procedure Execute; override;
public
Sito: String; //Out: Contiene l'html del sito web a cui si è fatto l'accesso
EndTime: TDateTime; //Out: Viene impostato con l'orario di quando è terminato l'accesso
constructor Create(Url: String; Mem: Boolean; Nom: String = ''; StTime: TDateTime = 0);
end;

Thankyou for your attention!

Lorenzo

Edited by: Lorenzo Crivellaro on Aug 4, 2015 9:57 AM

Edited by: Lorenzo Crivellaro on Aug 4, 2015 9:59 AM

Peter Below

Posts: 1,227
Registered: 12/16/99
Re: problem ntdll.dll? [Edit]
Click to report abuse...   Click to reply to this thread Reply
  Posted: Aug 5, 2015 4:05 AM   in response to: Lorenzo Crivell... in response to: Lorenzo Crivell...
Lorenzo Crivellaro wrote:

Are you using TThread descendents or a different threading
framework?
For multithread I use TThread descendents ( TMultiWeb =
class(TThread) )

OK, so the memory manager should be configured to be threadsafe.

procedure TMultiWeb.Execute;
var
Web: TIdHTTP;
hIOHand: TIdSSLIOHandlerSocketOpenSSL;
begin
//Il Thread attende che venga raggiunta l'ora di esecuzione (se
indicata):
while (Now < FStTime) do //or (ElabMultiWeb > MAX_MULTI_WEB) do
Application.ProcessMessages;

Argh! Why are you doing that??? ProcessMessages should only be used in
the main thread context, and even there it is a bad idea! To wait for
something in a secondary thread you use Sleep, and your loop condition
should also check the terminated property and bail out if it is true:

while (Now < FStTime) and not Terminated do
Sleep(50); // select an appriopriate wait interval
if Terminated then Exit;


Web := TIdHTTP.Create(nil);
hIOHand := TIdSSLIOHandlerSocketOpenSSL.Create(nil);

The code using these two objects needs to be wrapped into a try finally
block to make sure these two objects are destroyed even if something
goes wrong before you get to call web.get. Unlikely in this case, I
know, but it is a good habit to get into, especially if you work with
classes that manage external resources, like socket handles or files.
Objects should also be destroyed in the inverse sequence they are
created in. I would structure this code section as

hIOHand := nil;
Web := TIDHttp.Create(nil);
try
hIOHand := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
hIOHand.SSLOptions.Method := sslvTLSv1;
Web.IOHandler := hIOHand;
Web.HandleRedirects := True;

Web.Request.UserAgent := INET_USERAGENT; //Custom user agent string
Web.RedirectMaximum := INET_REDIRECT_MAX; //Maximum redirects
Web.HandleRedirects := INET_REDIRECT_MAX <> 0; //Handle redirects
Web.ReadTimeOut := INET_TIMEOUT_SECS * 1000; //Read timeout msec

try
Sito := Web.Get(FUrl); //Do the request
except
Sito := 'Errore accesso web';
end;
finally
hIOHand.Free;
Web.Free;
end;
if (not FMem) then
Synchronize(ScriviFile);

EndTime := Now;
// Dec(ElabMultiWeb);
end; {TMultiWeb.Execute}

--
Peter Below (TeamB)

Lorenzo Crivell...

Posts: 4
Registered: 7/11/02
Re: problem ntdll.dll? [Edit]
Click to report abuse...   Click to reply to this thread Reply
  Posted: Aug 5, 2015 2:45 PM   in response to: Peter Below in response to: Peter Below
Peter Below (TeamB)

Hello Peter,
i adjust my routine multithread as your instruction (im happy to have a correct routine), but i found the problem in an other instructions:

Canc := StringOfChar('~', Length(Car));
ArrG[Num].Psz := I - Length(Car) - 1;
ArrG[Num].Lng := Length(Car);
ArrG[Num].Org := Car;
Stg := StringReplace(Stg, Car, Canc, []);
ArrG[Num].Num := StrToInt(Car);
Car := '';
Inc(Num);

if (I2 >= High(ArrG)) then
SetLength(ArrG, Length(ArrG)+100);

in the last if I used a wrong variable I2 and not the correct Num....

thankyou for your precius information... but i have a question for you:

while (Now < FStTime) and not Terminated do
Sleep(50); // select an appriopriate wait interval
if Terminated then Exit;

why do you use Terminated var if is impossible that the routine is terminated (we are inside the routine) or terminated indicate another information?

what is the correct way to control a max number of multithread that the program run in the same time?
i used an external var... but i think in not a good idea

Lorenzo

Edited by: Lorenzo Crivellaro on Aug 5, 2015 2:46 PM
Peter Below

Posts: 1,227
Registered: 12/16/99
Re: problem ntdll.dll? [Edit] [Edit]
Click to report abuse...   Click to reply to this thread Reply
  Posted: Aug 6, 2015 8:31 AM   in response to: Lorenzo Crivell... in response to: Lorenzo Crivell...
Lorenzo Crivellaro wrote:

Hello Peter,
i adjust my routine multithread as your instruction (im happy to
have a correct routine), but i found the problem in an other
instructions:

Glad you found the source of the problem.

thankyou for your precius information... but i have a question for
you:

while (Now < FStTime) and not Terminated do
Sleep(50); // select an appriopriate wait interval
if Terminated then Exit;

why do you use Terminated var if is impossible that the routine is
terminated (we are inside the routine) or terminated indicate another
information?

A thread can be terminated from outside, e.g. when the application is
closing and some code tries to Free the thread object. The default
TThread destructor calls Terminate and then waits for the thread to get
out of the Execute method. If said method does not check for Terminated
this wait will never return and thus your application will not end
normally, or only after a lengthy interval. Checking Terminated
regularly inside a thread's Execute method is another habit one should
cultivate <g>.

what is the correct way to control a max number of multithread that
the program run in the same time? i used an external var... but i
think in not a good idea

If you want to have the counter internal to the thread class, use a
private class var. Make sure to use a thread-safe mechanism to
increment and decrement this variable. The TInterlocked class has
Increment and Decrement methods that are thread-safe, other than Inc
and Dec. Those are only safe for types were the operation is atomic on
the machine code level, and that is only guaranteed for byte, as far as
I know. Depends on the CPU...

However, a simple counter is still vulnerable to race conditions in a
multithreaded environment, since you have to use it in a two-step
manner: check its value, if below the max number, increment it and
create the new thread, else bail out. Between the test and the
increment another thread may have jumped in (unless threads are only
created by one single application thread, then this is not a problem).
You can mitigate that by using TInterlocked.CompareExchange for the
incrementation, that allows you to detect whether the counter has been
altered by another thread after you got its value first.

Using a TSemaphore instead of a counter does not have this problem, but
it has another: If the thread aiming to create a new worker cannot
acquire the semaphore because the maximum number of allowed threads has
been reached the thread will be blocked until one of the running
threads ends and releases the semaphore again.

--
Peter Below (TeamB)
Legend
Helpful Answer (5 pts)
Correct Answer (10 pts)

Server Response from: ETNAJIVE02