title: Weird structure member alignment in C++ / gSoap 2.8.2
body: <p>I've encountered a weird structure member alignment issue in C++. This happens when using gSoap 2.8.2. gSoap defines this struct:</p>
  
  <pre><code>struct SOAP_STD_API soap
  { short state;          /* 0 = uninitialized, 1 = initialized, 2 = copy of another soap struct */
    short version;        /* 1 = SOAP1.1 and 2 = SOAP1.2 (set automatically from namespace URI in nsmap table) */
    soap_mode mode;
    soap_mode imode;
    soap_mode omode;
    const char *float_format; /* user-definable format string for floats (&lt;1024 chars) */
    const char *double_format;    /* user-definable format string for doubles (&lt;1024 chars) */
    const char *dime_id_format;   /* user-definable format string for integer DIME id (&lt;SOAP_TAGLEN chars) */
    const char *http_version; /* HTTP version used "1.0" or "1.1" */
    const char *http_content; /* optional custom response content type (with SOAP_FILE) */
    const char *encodingStyle;    /* default = NULL which means that SOAP encoding is used */
    const char *actor;        /* SOAP-ENV:actor or role attribute value */
    const char *lang;     /* xml:lang attribute value of SOAP-ENV:Text */
    int recv_timeout;     /* when &gt; 0, gives socket recv timeout in seconds, &lt; 0 in usec */
    int send_timeout;     /* when &gt; 0, gives socket send timeout in seconds, &lt; 0 in usec */
    int connect_timeout;      /* when &gt; 0, gives socket connect() timeout in seconds, &lt; 0 in usec */
    int accept_timeout;       /* when &gt; 0, gives socket accept() timeout in seconds, &lt; 0 in usec */
    int socket_flags;     /* socket recv() and send() flags, e.g. set to MSG_NOSIGNAL to disable sigpipe */
    int connect_flags;        /* connect() SOL_SOCKET sockopt flags, e.g. set to SO_DEBUG to debug socket */
    int bind_flags;       /* bind() SOL_SOCKET sockopt flags, e.g. set to SO_REUSEADDR to enable reuse */
    int accept_flags;     /* accept() SOL_SOCKET sockopt flags */
    unsigned short linger_time;   /* linger time for SO_LINGER option */
    const struct Namespace *namespaces;   /* Pointer to global namespace mapping table */
    struct Namespace *local_namespaces;   /* Local namespace mapping table */
    struct soap_nlist *nlist; /* namespace stack */
    struct soap_blist *blist; /* block allocation stack */
    struct soap_clist *clist; /* class instance allocation list */
    void *alist;          /* memory allocation (malloc) list */
    struct soap_ilist *iht[SOAP_IDHASH];
    struct soap_plist *pht[SOAP_PTRHASH];
    struct soap_pblk *pblk;   /* plist block allocation */
    short pidx;           /* plist block allocation */
    struct SOAP_ENV__Header *header;
    struct SOAP_ENV__Fault *fault;
    int idnum;
    void *user;           /* for user to pass user-defined data */
    void *data[4];        /* extension data = {smdevp, mecevp, ...} */
    struct soap_plugin *plugins;  /* linked list of plug-in data */
    const char *userid;       /* HTTP Basic authorization userid */
    const char *passwd;       /* HTTP Basic authorization passwd */
    int (*fpost)(struct soap*, const char*, const char*, int, const char*, const char*, size_t);
    int (*fget)(struct soap*);    /* HTTP GET hook (not set by default) */
    int (*fput)(struct soap*);    /* HTTP PUT hook (handled as POST) */
    int (*fdel)(struct soap*);    /* HTTP DELETE hook (not set by default) */
    int (*fopt)(struct soap*);    /* HTTP OPTIONS hook (not set by default) */
    int (*fhead)(struct soap*);   /* HTTP HEAD hook (not set by default) */
    int (*fform)(struct soap*);   /* HTTP/HTML form handler for plugins */
    int (*fposthdr)(struct soap*, const char*, const char*);
    int (*fresponse)(struct soap*, int, size_t);
    int (*fparse)(struct soap*);
    int (*fparsehdr)(struct soap*, const char*, const char*);
    int (*fheader)(struct soap*);
    int (*fresolve)(struct soap*, const char*, struct in_addr* inaddr);
    int (*fconnect)(struct soap*, const char*, const char*, int);
    int (*fdisconnect)(struct soap*);
    int (*fclosesocket)(struct soap*, SOAP_SOCKET);
    int (*fshutdownsocket)(struct soap*, SOAP_SOCKET, int);
    SOAP_SOCKET (*fopen)(struct soap*, const char*, const char*, int);
    SOAP_SOCKET (*faccept)(struct soap*, SOAP_SOCKET, struct sockaddr*, int *n);
    int (*fclose)(struct soap*);
    int (*fsend)(struct soap*, const char*, size_t);
    size_t (*frecv)(struct soap*, char*, size_t);
    int (*fpoll)(struct soap*);
    int (*fselect)(struct soap*, SOAP_SOCKET, int, int, void*);
    void *fselect_param;
    void (*fseterror)(struct soap*, const char **c, const char **s);
    int (*fignore)(struct soap*, const char*);
    int (*fserveloop)(struct soap*);
    void *(*fplugin)(struct soap*, const char*);
    void *(*fmalloc)(struct soap*, size_t);
  #ifndef WITH_LEANER
    int (*feltbegin)(struct soap*, const char*);
    int (*feltendin)(struct soap*, const char*, const char*);
    int (*feltbegout)(struct soap*, const char*);
    int (*feltendout)(struct soap*, const char*);
    int (*fprepareinitsend)(struct soap*);
    int (*fprepareinitrecv)(struct soap*);
    int (*fpreparesend)(struct soap*, const char*, size_t);
    int (*fpreparerecv)(struct soap*, const char*, size_t);
    int (*fpreparefinalsend)(struct soap*);
    int (*fpreparefinalrecv)(struct soap*);
    int filterstop;
    int (*ffiltersend)(struct soap*, const char**, size_t*);
    int (*ffilterrecv)(struct soap*, char*, size_t*, size_t);
    void *(*fdimereadopen)(struct soap*, void*, const char*, const char*, const char*);
    void *(*fdimewriteopen)(struct soap*, const char*, const char*, const char*);
    void (*fdimereadclose)(struct soap*, void*);
    void (*fdimewriteclose)(struct soap*, void*);
    size_t (*fdimeread)(struct soap*, void*, char*, size_t);
    int (*fdimewrite)(struct soap*, void*, const char*, size_t);
    void *(*fmimereadopen)(struct soap*, void*, const char*, const char*, const char*);
    void *(*fmimewriteopen)(struct soap*, void*, const char*, const char*, const char*, enum soap_mime_encoding);
    void (*fmimereadclose)(struct soap*, void*);
    void (*fmimewriteclose)(struct soap*, void*);
    size_t (*fmimeread)(struct soap*, void*, char*, size_t);
    int (*fmimewrite)(struct soap*, void*, const char*, size_t);
  #endif
    SOAP_SOCKET master;
    SOAP_SOCKET socket;
  #if defined(__cplusplus) &amp;&amp; !defined(WITH_LEAN) &amp;&amp; !defined(WITH_COMPAT)
    std::ostream *os;
    std::istream *is;
  #else
    void *os;     /* preserve struct size */
    void *is;     /* preserve struct size */
  #endif
  #ifndef UNDER_CE
    int sendfd;       /* WinCE FD to send */
    int recvfd;       /* WinCE FD to receive */
  #else
    FILE *sendfd;
    FILE *recvfd;
  #endif
    size_t bufidx;    /* index in soap.buf[] */
    size_t buflen;    /* length of soap.buf[] content */
    soap_wchar ahead; /* parser lookahead */
    short cdata;      /* CDATA parser state */
    short body;       /* parsed XML element has a body or not */
    unsigned int level;   /* XML nesting level */
    size_t count;     /* message length counter */
    size_t length;    /* message length as set by HTTP header */
    char *labbuf;     /* look-aside buffer */
    size_t lablen;    /* look-aside buffer allocated length */
    size_t labidx;    /* look-aside buffer index to available part */
    char buf[SOAP_BUFLEN];/* send and receive buffer */
    char msgbuf[1024];    /* in/out buffer for HTTP/MIME headers &gt;=1024 bytes */
    char tmpbuf[1024];    /* in/out buffer for HTTP/MIME headers, simpleType values, element and attribute tag names, and DIME must be &gt;=1024 bytes */
    char tag[SOAP_TAGLEN];
    char id[SOAP_TAGLEN];
    char href[SOAP_TAGLEN];
    char type[SOAP_TAGLEN];
    char arrayType[SOAP_TAGLEN];
    char arraySize[SOAP_TAGLEN];
    char arrayOffset[SOAP_TAGLEN];
    short other;
    short position;
    int positions[SOAP_MAXDIMS];
    short root;
    struct soap_attribute *attributes;    /* attribute list */
    short encoding;   /* when set, output encodingStyle */
    short mustUnderstand; /* a mustUnderstand element was parsed or is output */
    short null;       /* parsed XML is xsi:nil */
    short ns;     /* when not set, output full xmlns bindings */
    short part;       /* SOAP part state (header or body) */
    short event;      /* engine events and states for use by plugins */
    short alloced;
    short peeked;
    size_t chunksize;
    size_t chunkbuflen;
    char endpoint[SOAP_TAGLEN];
    char path[SOAP_TAGLEN];
    char host[SOAP_TAGLEN];
    char *action;
    char *authrealm;      /* HTTP authentication realm */
    char *prolog;         /* XML declaration prolog */
    unsigned long ip;     /* IP number */
    int port;         /* port number */
    short keep_alive;     /* connection should be kept open */
    short tcp_keep_alive;     /* enable SO_KEEPALIVE */
    unsigned int tcp_keep_idle;   /* set TCP_KEEPIDLE */
    unsigned int tcp_keep_intvl;  /* set TCP_KEEPINTVL */
    unsigned int tcp_keep_cnt;    /* set TCP_KEEPCNT */
    unsigned int max_keep_alive;  /* maximum keep-alive session (default=100) */
    const char *proxy_http_version;/* HTTP version of proxy "1.0" or "1.1" */
    const char *proxy_host;   /* Proxy Server host name */
    int proxy_port;       /* Proxy Server port (default = 8080) */
    const char *proxy_userid; /* Proxy Authorization user name */
    const char *proxy_passwd; /* Proxy Authorization password */
    const char *proxy_from;   /* X-Forwarding-For header returned by proxy */
    int status;           /* -1 when request, else error code to be returned by server */
    int error;
    int errmode;
    int errnum;
  #ifndef WITH_LEANER
    struct soap_dom_element *dom;
    struct soap_dime dime;
    struct soap_mime mime;
    struct soap_xlist *xlist;
  #endif
  #if !defined(WITH_LEAN) || defined(SOAP_DEBUG)
    const char *logfile[SOAP_MAXLOGS];
    FILE *fdebug[SOAP_MAXLOGS];
    struct soap_mlist *mht[SOAP_PTRHASH];
  #endif
  #ifndef WITH_LEAN
    const char *wsuid;        /* space-separated string of element tags */
    const char *c14nexclude;  /* space-separated string of prefixes */
    struct soap_cookie *cookies;
    const char *cookie_domain;
    const char *cookie_path;
    int cookie_max;
  #endif
  #ifndef WITH_NOIO
    int ipv6_multicast_if; /* in6addr-&gt;sin6_scope_id IPv6 value */
    char* ipv4_multicast_if; /* IP_MULTICAST_IF IPv4 setsockopt interface_addr */
    unsigned char ipv4_multicast_ttl; /* IP_MULTICAST_TTL value 0..255 */
  #ifdef WITH_IPV6
    struct sockaddr_storage peer; /* IPv6: set by soap_accept and by UDP recv */
  #else
    struct sockaddr_in peer;  /* IPv4: set by soap_connect/soap_accept and by UDP recv */
  #endif
  #endif
    size_t peerlen;
  #if defined(WITH_OPENSSL)   /* OpenSSL */
    int (*fsslauth)(struct soap*);
    int (*fsslverify)(int, X509_STORE_CTX*);
    BIO *bio;
    SSL *ssl;
    SSL_CTX *ctx;
    SSL_SESSION *session;
    const char *dhfile;
    const char *randfile;
  #elif defined(WITH_GNUTLS)      /* GNUTLS */
    int (*fsslauth)(struct soap*);
    void *fsslverify;
    gnutls_certificate_credentials_t xcred;   /* cert pointer */
    gnutls_anon_client_credentials_t acred;   /* anon pointer */
    gnutls_priority_t cache;          /* priority cache pointer */
    gnutls_session_t session;         /* session pointer */
    gnutls_dh_params_t dh_params;
    gnutls_rsa_params_t rsa_params;
  #else               /* No SSL/TLS */
    void *fsslauth;       /* dummy members, to preserve struct size */
    void *fsslverify;
    void *bio;
    void *ssl;
    void *ctx;
    void *session;
    void *dh_params;
    void *rsa_params;
  #endif
    unsigned short ssl_flags;
    const char *keyfile;
    const char *password;
    const char *cafile;
    const char *capath;
    const char *crlfile;
    char session_host[SOAP_TAGLEN];
    int session_port;
  #ifdef WITH_C_LOCALE
    locale_t c_locale;        /* set to C locale by default */
  #else
    void *c_locale;
  #endif
  #ifdef WITH_ZLIB
    z_stream *d_stream;       /* decompression stream */
    uLong z_crc;          /* internal gzip crc */
  #else
    void *d_stream;       /* dummy members, to preserve struct size */
    soap_int32 z_crc;
  #endif
    const char *z_dict;       /* support for zlib static dictionaries */
    unsigned int z_dict_len;
    short zlib_state;     /* SOAP_ZLIB_NONE, SOAP_ZLIB_DEFLATE, or SOAP_ZLIB_INFLATE */
    short zlib_in;        /* SOAP_ZLIB_NONE, SOAP_ZLIB_DEFLATE, or SOAP_ZLIB_GZIP */
    short zlib_out;       /* SOAP_ZLIB_NONE, SOAP_ZLIB_DEFLATE, or SOAP_ZLIB_GZIP */
    char *z_buf;          /* buffer */
    size_t z_buflen;
    unsigned short z_level;   /* compression level to be used (0=none, 1=fast to 9=best) */
    float z_ratio_in;     /* detected compression ratio compressed_length/length of inbound message */
    float z_ratio_out;        /* detected compression ratio compressed_length/length of outbound message */
  #ifdef WMW_RPM_IO       /* VxWorks */
    void *rpmreqid;
  #endif
  #ifdef __cplusplus
    soap();
    soap(soap_mode);
    soap(soap_mode, soap_mode);
    soap(const struct soap&amp;);
    virtual ~soap();
  #else
    void (*dummy)(void);
  #endif
  };
  </code></pre>
  
  <p>which is later on used widely through the library. I needed to modify the behavior a bit, but even a simple line like</p>
  
  <pre><code>struct soap *soap;
  ...
  // soap-&gt;error is 401 up to this point
  soap-&gt;error = 0;
  // soap-&gt;error is still 401, at least according to VS2008 debugger
  </code></pre>
  
  <p>First thing i did was look at the assembly:</p>
  
  <pre><code>soap-&gt;error = 0;
  172A35D8  mov         eax,dword ptr [soap] 
  172A35DB  mov         dword ptr [eax+191A4h],0 
  </code></pre>
  
  <p>while, <code>&amp;soap-&gt;error = 0x0cb3ead0</code> and <code>soap = 0x0cb25930</code>, and <code>0x0cb3ead0 - 0x0cb25930 = 0x191A0</code> which is 4 bytes less. So either the debugger is wrong , either the assembly, but since the library works, the doubts are highly on the debugger. Either way it is quite impossible to alter the code in these circumstances.</p>
  
  <p>Any suggestions what could cause this ? Is my pointer arithmetic wrong somewhere? I tried</p>
  
  <pre><code>#pragma pack(push)
  #pragma pack(1)
  ...
  #pragma pack(pop)
  </code></pre>
  
  <p>around the structure definition but that did not help.</p>