免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 46626 | 回复: 88
打印 上一主题 下一主题

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

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-05-17 00:26 |只看该作者 |正序浏览
我想举一个自己最近在项目中犯的错误来说明要踏踏实实做人,不要做装B青年
在代码中,我需要在一个library和一个daemon之间通过socket传送数据包,包的格式定义如下(为了简化,我就用最简单的数据类型举例):

  1. typedef struct {
  2.         int head;
  3.         int size; //指明整个包的长度
  4.         char reply;
  5.         char data[0];
  6. } packet;

  7. packet*  cmd = malloc (sizeof(packet) + 20);
  8. memcpy (packet->data, some_data, 20);
复制代码


daemon将上面分配的cmd包发送给library,library接收到包后,需要将data字段中的数据取出来。size指明了整个包的长度,但没有字段指明数据的长度。我需要这么一个指明数据长度的字段吗?作为一个装B青年,我认为当然不需要,于是我这样来计算数据的长度:

  1. #define offsetof(type, element) ((int)&((type *)0)->element)
  2. static inline size_t packet_data_len(packet* cmd) {
  3.     assert(cmd);
  4.     return cmd->size - offsetof(packet, data);
  5. }

  6. memcpy (buffer_to_receive_data, cmd->data, packet_data_len (cmd));
复制代码


于是乎,这段程序成功的给我带来了无数的bug,莫名奇妙的segfault,奇怪的数据错误,还是有部分时间的正常工作。当然,最终我还是找到了问题:
sizeof (packet) == 12;
这是合理的,char reply被padding成了4个字节,而char data[0]字节为0。
但,offsetof(packet, data) == 9,在计算偏移时,char reply为一个字节,没有padding。
所以packet_data_len每次都会返回比真实的数据多3个字节 ……

最后我还是老老实实加了个data_len字段指明数据的长度,并告诫自己,本本分分写程序,莫装B ……

论坛徽章:
0
89 [报告]
发表于 2011-11-28 16:26 |只看该作者
好多开源软件以及内核中都大量使用了data【0】的技巧,所以一定要学会怎么用

论坛徽章:
0
88 [报告]
发表于 2011-11-26 14:34 |只看该作者
我想举一个自己最近在项目中犯的错误来说明要踏踏实实做人,不要做装B青年
在代码中,我需要在一个libr ...
zx_wing 发表于 2009-05-17 00:26



为什么不
#pragma pack(1) 一字节对齐呢????????????

论坛徽章:
0
87 [报告]
发表于 2010-07-15 23:53 |只看该作者
问题不是出在 char data[0]上,因对struct的理解不到位,程序出问题而不敢再用 char data[0]并不能实际解决问题。

论坛徽章:
0
86 [报告]
发表于 2010-07-15 22:26 |只看该作者
呵呵,小伙子水平不高口气不小。
首先char data[1]解决不了问题,char data[0]不是C标准,前者是C标准而 ...
zx_wing 发表于 2009-05-17 22:29



    长见识了,今天才知道有gcc manual这个东东

论坛徽章:
1
数据库技术版块每日发帖之星
日期:2016-05-27 06:20:00
85 [报告]
发表于 2010-07-15 20:43 |只看该作者
得好复杂,你把结构体改为:
typedef struct {
        int head;
        int size; //指明整个包的长 ...
yulc 发表于 2009-05-18 11:29



    恩 这个加char pad[3]的办法在当前环境下是可行的,但它针对的是特定的补齐方案,万一int占8个字节呢? 那就要改为char pad[7]了么。。。。。。。。。

论坛徽章:
0
84 [报告]
发表于 2009-06-14 23:00 |只看该作者
很典型的把简单的问题复杂化。

无聊贴。

论坛徽章:
0
83 [报告]
发表于 2009-06-14 21:54 |只看该作者
原帖由 雨过白鹭洲 于 2009-5-27 00:29 发表
不同机器间的数据交换,除了对齐,还有大端小端等等问题

你定义struct来传报文,当然会出问题了;传二进制数据也同样是不可靠的

感谢楼主分享经验。。


还是这位兄弟,是解决问题的人,要解决问题,就要学此位兄弟的态度

论坛徽章:
0
82 [报告]
发表于 2009-06-14 21:47 |只看该作者
网络间传递raw bin 数据,只能说这个想法太让人无语了。

论坛徽章:
0
81 [报告]
发表于 2009-05-27 02:20 |只看该作者
晕,看你们俩的技术交流有趣 看到第4页就没看了
也不是很懂
  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP