20.1.4 Dynamic-Link Libraries and Stacks

Unlike a task module, a dynamic-link module does not have its own stack. Instead, it uses the stack segment of the task that called it. This can create problems when a library calls a function that treats the DS and SS registers as if they hold the same address. This problem is most likely to occur in small- and medium-model dynamic-link libraries, since pointers in these models are, by default, near pointers. Many C run-time library functions, for example, treat DS and SS as equal. You must take care when you call these functions from within your dynamic-link library.

Your library can also encounter difficulties when calling user-written functions. Consider, for example, a dynamic-link library containing a function that declares a variable within the body of the function. The address of this function will be relative to the stack of the task that called the library. If this function passes the variable to a second function that expects a near pointer, the second function will assume that the address it receives is relative to the dynamic-link library's data segment rather than to the stack segment of the task that called it.

The following example shows a function in a dynamic-link library passing a variable from the stack, rather than from its data segment:

void DLLFunction(WORD wMyWord)
{
    char szMyString[10];
    .
    .
    .

    AnotherFunction(szMyString);
}

In this example, if AnotherFunction was declared as accepting a near pointer to a character array (char NEAR *), it will interpret the address it receives as being an offset of the data segment, rather than of the stack segment of the task that called the library.

To ensure that your dynamic-link library does not attempt to pass stack variables to functions that expect near pointers, you should compile your library modules by using the CL /Aw option. This will produce warning messages that indicate when the library is making a call to a function that treats DS and SS as equal. When you receive a warning for a particular function, you can either remove that function call from your library, or rewrite the library source module so that it does not pass a stack variable to that function.