Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
29279 Discussions

Access violation on return from CreateThread

michael_green
Beginner
1,781 Views

Hi All,

I get an access violation on return from CreateThread.

The call to create the thread is made under WM_CREATE in a standard Windows application, and in the thread I run a DLL that checks a licence key in the registry. If there's an error it issues a message, but otherwise - normally - it takes no action. The DLL requires no arguments so I create the thread with 0 as the lpParameter (4th argument) ...

handles(1) = CreateThread(NULL,0,loc(ExecRtnl),0,0,loc(idThread))

The relevant code for ExecRtnl is:

integer*4 hlic,iret

pointer (licaddr,rtn_checklicence)

...

!Get handle of the licence dll

hlic = loadlibrary("Licence.dll"C)

if(hlic==0)call prgerr(0,'Error locating Licence.dll','aFMIS/ExecRtnl','X')

!Get address of the licence function

licaddr = getprocaddress(hlic,"CHECKLICENCE"C)

if(licaddr==0)call prgerr(0,'Error locating routine licence in Licence.dll.','aFMIS/ExecRtnl','X')

!Check licence against that encrypted in the registry.

call rtn_checklicence

iret = freelibrary(hlic)

ExecRtnl = 1

The DLL works well, but on return to the main program, after all other jobs under WM_CREATE have been completed, I get an access violation. I have found 3 ways around this:

1: Pass a dummy argument from the call to CreateThread all the way through to the DLL.

2: Disable an internal read (string to integer) in the DLL.

3: Disable the call to FreeLibrary on return of the DLL.

Any of the above actions removes the access violation, and the first and third ones enable the program to proceed normally.

I have used this general technique for creating threads and running DLLs many times before without problems, but this is the first time I have used a DLL the requires no arguments. I have spent many hours reading through websites and studying examples written in C and cannot see where I am going wrong.

Does anyone have any suggestions?

With many thanks in advance

Mike

0 Kudos
3 Replies
ZlamalJakub
New Contributor III
1,781 Views

I remember that there is some problem with createThread api function I use

BeginThreadEx(null_security_attributes,0,LOC(StartThreadFunc),0,0,LOC(iThreadID))

instead and there are no problems (it was mentioned somewhere long ago).

Jakub

0 Kudos
Jugoslav_Dujic
Valued Contributor II
1,781 Views
I have used this general technique for creating threads and running DLLs many times before without problems, but this is the first time I have used a DLL the requires no arguments. I have spent many hours reading through websites and studying examples written in C and cannot see where I am going wrong.

Do you mean that it literally has no arguments? You must not do that. When you utilize any sort of callback technique, the called procedure must have fixed interface. Compare e.g. DlgSetSub, where the called routine must have prototype SUBROUTINE(Dlg, id, iEvent).

The error gets exposed when the target routine is STDCALL: there, the callee cleans the stack. In your case, the caller (CreateThread) pushes there one, but the called routine on exit pops none, creating a mismatch (likely resulting in a wrong return address or who knows). With C (__cdecl) (Ifort default), you could get away with that.

So, in a nutshell, your thread function must be a STDCALL function with exactly 1 argument, which you need not necessarily use. If you cannot change the prototype, write a wrapper function.

0 Kudos
michael_green
Beginner
1,781 Views

Thanks for replies.

In my original post I was perhaps not quite as clear as I would have liked - I had already tried passing dummy arguments into and out of the DLL in the created thread, but still had problems.

I have solved the problem by including a call to ExitThread in the DLL - something I have not done before in many other DLLs. I quote from the online documentation:

"ExitThread is the preferred method of exiting a thread in C code. However, in C++ code, the thread is exited before any destructors can be called or any other automatic cleanup can be performed. Therefore, in C++ code, you should return from your thread function."

I assumed, since all my other threads simply returned successfully, that the C++ method was the way to go. I would love to hear some comments and some theory on this point.

With many thanks in advance,

Mike

0 Kudos
Reply