免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: zx_wing
打印 上一主题 下一主题

char[0], sizeof和struct padding [复制链接]

论坛徽章:
0
51 [报告]
发表于 2009-05-18 12:32 |只看该作者
原帖由 zx_wing 于 2009-5-17 00:26 发表
我想举一个自己最近在项目中犯的错误来说明要踏踏实实做人,不要做装B青年
在代码中,我需要在一个library和一个daemon之间通过socket传送数据包,包的格式定义如下(为了简化,我就用最简单的数据类型举例 ...


其实,我觉得,LZ把
  1. typedef struct {
  2.         int head;
  3.         int size; //指明整个包的长度
  4.         char reply;
  5.         char data[0];
  6. } packet;
复制代码

改为
  1. typedef struct {
  2. struct {
  3.         int head;
  4.         int size; //指明整个包的长度
  5.         char reply;
  6. };
  7.         char data[0];
  8. } packet;
复制代码

就OK了。

论坛徽章:
0
52 [报告]
发表于 2009-05-18 13:15 |只看该作者
LZ的帖子不是做经验分享的么? 怎么好多人理解成求助帖了…… 搞不懂

论坛徽章:
0
53 [报告]
发表于 2009-05-18 13:28 |只看该作者
原帖由 tyc611 于 2009-5-17 23:17 发表
如果是我,我会分为消息头和数据两部分


原帖由 ShadowStar 于 2009-5-18 12:32 发表


其实,我觉得,LZ把typedef struct {
        int head;
        int size; //指明整个包的长度
        char reply;
        char data[0];
} packet;

改为typedef struct {
struct {
        i ...


我觉得以上两位说的挺有道理的,呵呵。

论坛徽章:
0
54 [报告]
发表于 2009-05-18 13:42 |只看该作者
是找到了问题:
sizeof (packet) == 12;
这是合理的,char reply被padding成了4个字节,而char data[0]字节为0。
但,offsetof(packet, data) == 9,在计算偏移时,char reply为一个字节,没有padding。
所以packet_data_len每次都会返回比真实的数据多3个字节 ……

----------------------------
LZ分析的不对。
offsetof(packet, data)=9 说明没有将reply padding为4个字节。

论坛徽章:
0
55 [报告]
发表于 2009-05-18 13:51 |只看该作者
原帖由 思一克 于 2009-5-18 13:42 发表

----------------------------
LZ分析的不对。
offsetof(packet, data)=9 说明没有将reply padding为4个字节。

我在35楼已经讲了这个padding什么时候发生什么时候不发生
呵呵,data[0]也和前面的紧邻的
如果仅仅是malloc(sizeof(packet)),则data[1]情况变为:
head (4 bytes) size (4 bytes) reply (1 byte) data[1] (1 bytes) padding (2 bytes)
如果是data[0]:
head (4 bytes) size (4 bytes) reply (1 byte) data[0] (0 bytes) padding (3 bytes)

不管data[0],data[1],malloc(sizeof(packet) + 20)后,之后都没有padding。所以两者内存布局本质是一样的,把data[0]改成data[1]没有任何帮助。

论坛徽章:
0
56 [报告]
发表于 2009-05-18 13:55 |只看该作者
原帖由 zx_wing 于 2009-5-18 13:51 发表

我在35楼已经讲了这个padding什么时候发生什么时候不发生


知道了。
反正,你根据offsetof(data)的数值,如果是9,前面的char reply就无padding。就是紧密的。
如果是12, 就是有。

论坛徽章:
0
57 [报告]
发表于 2009-05-18 14:33 |只看该作者
原帖由 ShadowStar 于 2009-5-18 12:32 发表


其实,我觉得,LZ把typedef struct {
        int head;
        int size; //指明整个包的长度
        char reply;
        char data[0];
} packet;

改为typedef struct {
struct {
        i ...


支持这种做法,单独把包头独立出来定义成一个结构体逻辑上也是正确的,这种做法最好不过了.

论坛徽章:
0
58 [报告]
发表于 2009-05-18 14:44 |只看该作者
原帖由 converse 于 2009-5-18 14:33 发表


支持这种做法,单独把包头独立出来定义成一个结构体逻辑上也是正确的,这种做法最好不过了.

前面的定义主要是想说明问题而简化的,实际我的定义中间也嵌套了多个struct,

  1. struct sf_packet_cmd {
  2.     sf_packet_head_t head;
  3.     sf_cmd_t cmd;
  4.     bool_t is_reply;
  5.     char data[0];
  6. };
复制代码

问题是data前面还有一个变量。除非包装到完全把data独立出来。
写这篇帖子的目的主要是想说明最好还是不要写可能涉及到padding格式的代码,可能在x86下没问题了,换个平台又出问题了。哈哈,算个教训吧。

论坛徽章:
0
59 [报告]
发表于 2009-05-19 01:31 |只看该作者
了解了。

论坛徽章:
0
60 [报告]
发表于 2009-05-19 10:25 |只看该作者
在网络数据传输的情况我一般使用 #pragma pack(1) ... #pragma pack(), 也挺省事的。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP