INF:.EXE Linked with LLIBCMT Can't Call DLL Linked with CRTLIB

ID Number: Q50695

5.10 6.00 6.00a 6.00ax | 5.10 6.00 6.00a

MS-DOS | OS/2

Summary:

A design limitation in the C 5.1 and C 6.0 library support of OS/2

dynamic link libraries (DLL) prevents .EXE files that are statically

linked to the run time from calling DLL routines that are dynamically

linked to the run time. If you want to use DLLs that are linked to

CRTLIB.LIB or CEXAMPLE.LIB, you must create your .EXE files with the C

run-time DLL (CRTLIB.LIB in C 5.1 or CEXAMPLE.LIB in C 6.0).

More Information:

The following is a specific illustration of this (assume that you have

the following files):

TheExe.exe: Contains a call to FUNC, which is defined in TheDLL.dll

TheDLL.dll: Contains the function FUNC

TheDLL.dll is a multithreaded DLL, which is linked with CRTLIB.LIB

(the DLL version of the C run time).

In general, the file TheExe.exe can be linked with either LLIBCMT.LIB

or CRTLIB.LIB (depending upon whether you desire a statically or

dynamically linked C run-time). The following are examples of both

link statements:

1. Statically linked with LLIBCMT.LIB:

link TheExe.obj,,,Doscalls.lib Llibcmt.lib/nod, TheExe.def;

2. Dynamically linked with CRTLIB.LIB:

link TheExe.obj Crtexe.obj,,,Doscalls.lib Crtlib.lib/nod,TheExe.def;

However, because this example requires that TheExe.exe call FUNC, which

resides in TheDLL.dll, you must link with CRTLIB.LIB as detailed in #2

above.

The common symptom of linking your .EXE with LLIBCMT.LIB and calling a

multithreaded DLL routine is a general protection violation (GP

fault) upon entry into the DLL routine. The generated assembly for

this entry is listed below:

pop cx

pop dx

mov bp, sp

push ds

push 154F

pop ds

jb 02A0

mov es, word ptr [005E] <-- es loaded with trash (0)

mov ax, word ptr es:[0006] <-- GP fault.

This is an assumption that is not valid. The loading of ES assumes

that the C run-time DLL data area is already initialized. However, it

was not.

The reason why this initialization did not take place is explained in

the following scenarios:

Note: CRT refers to C run time.

1. There are multiple C start-up initializations that must occur at

process creation time:

a. TheEXE.EXE -- Has its own start up (__astart).

b. TheDLL.DLL -- Program's DLL must be initialized (C_INIT).

c. C run-time DLL -- CRT's DLL DGROUP must be initialized

(__CRT_INIT).

2. The way these initializations happen are as follows:

a. TheEXE.EXE -- Start up occurs "normally" when __astart gets

control.

b. TheDLL.DLL -- The user DLL has a starting address specified

internally so that OS/2 executes C_INIT each time a new process

connects to it.

c. C run-time DLL -- The CRT DLL initialization needs information

from the .EXE start up (for example, arguments, and so on). Thus,

the current scheme is that the .EXE start up (__astart code)

explicitly calls the CRT DLL start-up code (__CRT_INIT).

3. The problem: In this supplied scenario, the problem is that the

.EXE is not built with the CRT DLL model; thus, CRTEXE.OBJ is not

linked into the user's program. It is the CRTEXE.OBJ module that

makes the explicit call to __CRT_INIT to initialize the CRT DLL.

Because this initialization code never gets called, the CRT's

DGROUP is not initialized; later, when we load a value out of the

CRT's DGROUP into ES,

mov es, word ptr [005E] <-- es loaded with trash (0)

mov ax, word ptr es:[0006] <-- GP fault.

the value is invalid and you get the GP fault.

Note: A program is multithreaded when it is compiled with the

appropriate include files and linked with the libraries that support

multiple threads. A program does not have to call _beginthread() or

DosCreateThread to be multithreaded.

If a program is compiled and linked as such, then the above problem is

applicable regardless of the number of threads in the program. This

means that a program with no calls to DosCreateThread and/or

_beginthread() will lie within the scope of this problem if it is

built as a multithreaded executable.

Additional reference words: 5.10 6.00 6.00a 6.00ax