ID Number: Q45584
5.10 6.00 6.00a
OS/2
Summary:
SYMPTOMS
In Microsoft C versions 5.1, 6.0, and 6.0a for OS/2, taking the
address of an automatic variable in a DLL will cause the compiler
to issue the following warning:
address of frame variable taken, DS != SS
Whenever the DLL is called, it will cause a GP fault. When
"NONSHARED" is added to the DATA directive in the .DEF file, the
GP trapping stops.
CAUSE
If you're using small or medium memory model, your pointers are
2-byte pointers, which contain only the offset of the variable into
the data segment.
In compact, large, and huge models, pointers are 4 bytes,
containing both a segment and an offset.
When a DLL is executing, it uses your stack (normally in your
data segment) and the DLL's default data segment. Thus, you must
compile with /Au or /Aw, telling the compiler that it should not
assume (as it normally does) that DS (the default data segment
selector) and SS (the current stack segment selector) are the same.
All near (2-byte) pointers are assumed to be relative to the
current DS. When you take the address of a frame (automatic)
variable, this address is relative to SS. When SS == DS, as is the
usual case, this is not a problem. However, it does cause problems
in DLLs, where SS cannot be equal to DS.
RESOLUTION
There is no way to take a near address of a stack variable when
DS!=SS. You do have several alternatives, however:
1. Change to compact, large, or huge model. Since the pointers are
far pointers, you'll be able to represent the address properly.
In addition, all the run-time library functions accept such far
pointers.
2. Use a far pointer to hold the address. You can do this without
changing memory models. This method has the advantage that the
only pointer accesses that are slowed are the individual far
pointers used to access the stack. The disadvantage is that most
small and medium model library routines do not support far
pointers, so you must either avoid those routines or copy the
far data into the default data segment before calling the
routine. Please note that this is necessary only with routines
that accept pointers; routines that accept variables by value
aren't affected because the value of the expression doesn't
change when the pointer size does. It is strongly recommended
that you use prototypes and new-style declarations for ALL your
functions to prevent errors.
3. Rework the code to avoid the need for taking the address of frame
variables.
More Information:
The reason the trapping seems to stop when you changed the .DEF file
probably has more to do with the sizes of the segments involved -- in
one case, the address generated was larger than the maximum for that
segment; in the other, it happened not to be. In each case, the
address was wrong because the compiler used DS rather than SS.
Therefore, changing the data directive in the .DEF file covered up but
did not correct the error.
DLLs that use the C run-time library ALWAYS use NONSHARED default data
and instance initialization. Instance initialization is specified in
the LIBRARY statement of the .DEF file.
Additional reference words: 5.00 5.10 6.00 6.00a