When you use Delphi to write a multithreaded program with inexplicable memory errors, especially strings (string) operations;
Or the program terminates without any reason, and you need to carefully analyze the possibility that you have directly used the CreateThread.
C + + linker can set the form of the runtime itself and choose whether to support single-threaded or multithreaded mode.
Delphi is automatically discriminant, then how he automatically discriminant, it is necessary to see his system unit provided by the function Beginthread. I heard that in the VC also do not agree with the direct use of unprotected
CreateThread, also use a protected _beginthread.
{$IFDEF MSWindows}
function Beginthread (securityattributes:pointer; Stacksize:longword;
Threadfunc:tthreadfunc; Parameter:pointer; Creationflags:longword;
var threadid:longword): Integer;
Var
P:pthreadrec;
Begin
New (P);
P.func: = ThreadFunc;
P.parameter: = Parameter;
Ismultithread: = TRUE;
Result: = CreateThread (Securityattributes, StackSize, @ThreadWrapper, P,
Creationflags, ThreadID);
End
See "Ismultithread: = TRUE;" This sentence?
Find his definition in the global variable:
Ismultithread:boolean; {True If more than one thread}
And look at Threadwrapper:
{$IFDEF MSWindows}
function Threadwrapper (parameter:pointer): Integer; stdcall;
{$ELSE}
function Threadwrapper (parameter:pointer): Pointer; Cdecl
{$ENDIF}
Asm
{$IFDEF Pc_mapped_exceptions}
{Mark The top of the stack with a signature}
PUSH Unwindfi_topofstack
{$ENDIF}
Call _fpuinit
PUSH EBP
{$IFNDEF Pc_mapped_exceptions}
XOR ECX,ECX
PUSH Offset _exceptionhandler
MOV EDX,FS:[ECX]
PUSH EDX
MOV Fs:[ecx],esp
{$ENDIF}
MOV Eax,parameter
MOV Ecx,[eax]. Tthreadrec.parameter
MOV Edx,[eax]. Tthreadrec.func
PUSH ECX
PUSH EDX
Call _freemem
POP EDX
POP EAX
Call EDX
{$IFNDEF Pc_mapped_exceptions}
XOR Edx,edx
POP ECX
MOV FS:[EDX],ECX
POP ECX
{$ENDIF}
POP EBP
{$IFDEF Pc_mapped_exceptions}
{Ditch our TOS marker}
ADD ESP, 4
{$ENDIF}
End
Here Delphi helps you set up the thread's SEH handler function.
In Delphi, we should use beginthread and throw away CreateThread.
*****************************************************************************
Bloggers: Problems in practical applications
function Getguiyue (abuffer:parraybyte): Boolean; stdcall; External ' Guiyue.dll ';
An exception occurred when I called the function Getguiyue.
Beginthread (nil,0, @GetGuiyue, Tempbuffer,0,threadid);
The reason is that the beginthread access function conflicts with the StdCall interface. So you need to write a reference function at call time
function Parseguiyue (abuffer:parraybyte): Boolean;
Begin
Getguiyue (Abuffer); Calling a function in a DLL
Endthread (0); function End Close Thread
End
This way, you can safely use the beginthread.
Beginthread (nil,0, @ParseGuiyue, Tempbuffer,0,threadid); Creating child threading parsing
However, it has also been suggested that beginthread use unsafe
There are two problems with Parseguiyue as a beginthread parameter.
1. The P parameter is invalid (Parseguiyue is fetched from the top of the stack and is actually passed in eax).
2. function does not return correctly (Parseguiyue the return address of the top of the stack as the P parameter, and takes the next indeterminate element as the return address)
So adding endthread in Mythreadfunc just lets the thread end execution before the function returns, and does not solve the first problem--and this can lead to a serious error, Because the P parameter in Parseguiyue is an address that points to the memory of the snippet (a position in the execution of the Threadwrapper function).
In addition, it appears that calling Endthread causes a Pthreadrec memory leak to be allocated in the beginthread.
[Do not use CreateThread directly in]delphi, we recommend using Beginthread