FIX: MIDL compiler structure packing problems (136500)



The information in this article applies to:

  • Microsoft Win32 Software Development Kit (SDK) 3.1
  • Microsoft Win32 Software Development Kit (SDK) 3.5
  • Microsoft Win32 Software Development Kit (SDK) 3.51
  • Microsoft Win32 Software Development Kit (SDK) 4.0

This article was previously published under Q136500

SYMPTOMS

An RPC application that uses stub code generated by MIDL throws memory exceptions, causes a general protection (GP) fault, or overwrites memory in the data heap. The RPC application is using a structure or union in the IDL file.

CAUSE

The /Zp (packing) option of the MIDL compiler does not affect the size of the structure; MIDL always uses a packing of 1. However, the /Zp option of the C compiler does increase the size of the structure. Because MIDL assumes a packing of one, it generates code that allocates less memory than what is actually needed.

You can verify the behavior of the MIDL compiler by searching your client stub code for _StubMsg.pfnAllocate. This call is present only with semi- interpreted stubs (the default MIDL option, /Os). Try compiling your IDL file with different /Zp settings, and notice that the memory allocated by _StubMsg.pfnAllocate is unchanged, though it should change to accommodate packing space.

RESOLUTION

There are three solutions to correct this problem:
  1. Use MIDL's /Oi option.

    -or-
  2. Use #pragma pack(1) in the stub code to use a packing of 1.

    -or-
  3. Pad your interface declaration to match the padding done by the C compiler.
Please see MORE INFORMATION for details.

STATUS

Microsoft has confirmed this to be a problem in MIDL 2.00.0102 for the Win32 SDK. This problem was corrected in MIDL 3.0 (shipped with Windows NT 4.0 beta SDK) and was corrected in Microsoft Windows 2000.

MORE INFORMATION

Fully interpreted stubs (MIDL option /Oi) use another approach for parameter marshaling, and this alternative approach does not have the problem with the packing. The stub code produced with /Oi is slightly slower, but for most applications the loss is negligible. If you decide to use the /Oi option, make sure your remote procedures are declared as __stdcall. Refer to the MIDL documentation for more information on /Oi.

If you are not interested in using the /Oi option, you can manually pad your interface declaration. To manually pad your interface declaration, you must first determine the packing used by the C compiler. Visual C++ 2.x for the x86 uses a packing of 4 by default. Otherwise, the packing is specified by /Zp or #pramga pack(). Each element must start on a multiple of the packing size.

The following example shows how to pad a structure with a packing of 4.
   typedef struct   // This struct goes in the C code
   {
      char c;
      long l;
   } PADDED_BY_COMPILER_STRUCT;

   typedef struct   // This struct goes in the IDL file
   {
      char c;
      char pad[3];  // Add 3 bytes to align the next field on byte 4
      long l;
   } MANUALLY_PADDED_IDL_STRUCT;
				
Another alternative is to wrap the stub code generated by MIDL with
   #pragma pack(1)
				
Each time MIDL generates the stub code, you must insert #pragma pack statements into the server stub.

For example:
   /* File created by MIDL compiler version 2.00.0102 */ 
   /* at Fri Aug 18 13:48:23 1995
    */ 
   //@@MIDL_FILE_HEADING(  )

   #pragma pack(1)         // Added to fix MIDL pack problem

   #include <string.h>
   #include "bug.h"

   ... code generated by MIDL ...

   #pragma pack()          // Added to revert to default packing
				

Modification Type:MajorLast Reviewed:10/16/2002
Keywords:kbAPI kbBug kbnetwork kbOSWin2000fix kbRPC KB136500