不同内存对齐方式 memcpy之后数据错误

一.背景:

1.使用#pragma定义结构体:RECV_CMD_DATA_t和RECV_CMD_PACK_t,按照1字节进行内存对齐

#pragma   pack(1)

typedef struct recv_cmd_data
{
    int              iType;
    long long        llInt;
    int              iLen;
    char             cStr[REPLY_STR_MAX_LEN];
}RECV_CMD_DATA_t;

typedef struct recv_cmd_pack
{
    int              iCnt;
    RECV_CMD_DATA_t  sCmdData[REPLY_TRANS_MAX_CNT];
}RECV_CMD_PACK_t;

#pragma   pack()

2.redis中定义的结构体:redisReply,按照4字节进行内存对齐

/* This is the reply object returned by redisCommand() */
typedef struct redisReply {
    int type; /* REDIS_REPLY_* */
    long long integer; /* The integer when type is REDIS_REPLY_INTEGER */
    int len; /* Length of string */
    char *str; /* Used for both REDIS_REPLY_ERROR and REDIS_REPLY_STRING */
    size_t elements; /* number of elements, for REDIS_REPLY_ARRAY */
    struct redisReply **element; /* elements vector for REDIS_REPLY_ARRAY */
} redisReply;

二:拷贝时结构体变量的值

1.redisReply变量:pRsp的值

VS2017中监视窗口:

不同内存对齐方式 memcpy之后数据错误_第1张图片

VS2017中内存窗口:


2.执行如下拷贝代码:

不同内存对齐方式 memcpy之后数据错误_第2张图片

即拷贝redisReply *pRsp指向内存的前三个字段

3.拷贝之后pRecvPack->sCmdData[0]的值如下:

不同内存对齐方式 memcpy之后数据错误_第3张图片

可以看出内存中并没有0x1a这个值

三:原因分析

redisReply结构体中的前三个字节占用内存20个字节,而pRecvPack->sCmdData[0]结构体中前三个字节占用内存16个字节,在拷贝的时候,宏REDIS_RECV_HEAD_LEN的长度是16个字节,所以拷贝了16个字节,出现了上图内存值的情况。

因为两个结构体中字段占用的内存分配是不匹配的,直接进行memcpy一定会导致字段值错误。

解决方法就是使用结构体指针,对每个字段进行分别赋值。

你可能感兴趣的:(【FAQ】)