c - 关于内存对齐的一些困惑

标签 c memory memory-management struct memory-alignment

#define     MCARD_CLS_TYPE_HD           1
#define     MCARD_SN_LEN                13

typedef struct mcard_ipc_list       
{                                   
    struct mcard_node *owner;

    struct
    {
        struct mcard_ipc_list *next;
        struct mcard_ipc_list *prev;
    } node;

    char sn_buf[MCARD_SN_LEN];  //13 byte

    struct len_str sn;          //8 byte                            
    struct mcard_smss smss[MCARD_CLS_TYPE_MIN + 1]; //16*3 byte
} _mcard_ipc_list;


struct mcard_smss           *smss = NULL;
struct mcard_node           *mnode = NULL;
...
smss = mnode->ipc_head.list->smss + MCARD_CLS_TYPE_HD;

问题是 smss 中的数据在 MFC 应用程序中不正确,但在 win32 控制台应用程序中正常!

我在 VS2010 的监 window 口中看到了变量的地址

win32控制台应用程序的结果:

smss                            0x0068af61
&mnode->ipc_head.list->smss[1]  0x0068af61  
&mnode->ipc_head.list->smss[0]  0x0068af51 
mnode->ipc_head.list->sn_buf    0x005aaf3c

MFC应用程序的结果:

smss                            0x00b1ad54 
&mnode->ipc_head.list->smss[1]  0x00b1ad51 
&mnode->ipc_head.list->smss[0]  0x00b1ad41 
mnode->ipc_head.list->sn_buf    0x00b1ad2c

对于 MFC 应用程序,很明显 smss wa 不等于 &mnode->ipc_head.list->smss[1]但有偏移量 0x3 !

我们看到 mnode->ipc_head.list->sn_buf占据13字节,未对齐!

我已经实际解决了这个问题,有两种方法:

(1)

#pragma pack(push, 1)
#pragma pack(pop)

(2)

#define     MCARD_SN_LEN                16

但是,当需要字节对齐时,我仍然对 win32 控制台应用程序和 MFC 应用程序之间的区别感到困惑!

问题:

  1. mnode->ipc_head.list->sn_buf 之间的距离&mnode->ipc_head.list->smss[0]21字节 在 win32 控制台应用程序和 MFC 应用程序中,不是 24字节,因为 (13 + 3) + 8表示 24 !但为什么呢?

  2. 内存地址在变量定义后应该是一定的,当然在变量定义后它们已经在内存中对齐了!和 smss = mnode->ipc_head.list->smss + MCARD_CLS_TYPE_HD;只是一个赋值语句, 为什么 MFC 应用程序中的结果不是 0x00b1ad51但是0x00b1ad54 ?而且这种现象是可以重现的!

那么,如果有人可以帮助我呢?


更新:

嗯,我写了一个 MFC 演示来解决第二个问题。

struct mcard_smss *smss = NULL;
smss = (struct mcard_smss *)0x00b1ad51;

但是,smss的值我在 vs2010 的监 window 口中看到不是 0x00b1ad54但是0x00b1ad51 !

有些变化和惊人!不知道为什么

最佳答案

继续评论,因为编译器可以在 struct 中设置字段的大小和填充,您可以使用 offsetof 宏(stddef.h ) 来确定成员在宏中的偏移量:

size_t offsetof(type, member);

offsetof 的手册页描述了它的用法并提供了示例。

The macro offsetof() returns the offset of the field member from the
start of the structure type.

This  macro  is useful because the sizes of the fields that compose a 
structure can vary across implementations, and compilers may insert 
different numbers of padding bytes between fields.  Consequently, an 
element's offset is not necessarily given by the sum of the sizes of 
the previous elements.

A compiler error will result if member is not aligned to a byte boundary
(i.e., it is a bit field).

很高兴对您有所帮助,如果您还有其他问题,请告诉我。

关于c - 关于内存对齐的一些困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38965992/

相关文章:

C 有向图实现选择

c - 如何更改 objdump 输出格式?

c - “#define setId(ptr, value) ((ptr)->id = (value), 0) 是什么意思

java - java 的 native 内存跟踪输出的 "other"部分有什么内容?

ruby-on-rails - 有没有更有效的方法来存储商店的营业时间?

c - 返回后打印一些东西

PHP - 执行长脚本时可能遇到的障碍

java - 对java中的内存感到困惑

iphone - “EXC_BAD_ACCESS"收到信号

c - 在 mcu 上的 malloc 之后需要一个 free()(即使数组/指针总是在使用中)?