结构体成员最后一个定义0长度数组
2015-08-20 10:06
393 查看
问题:最近看IO 块设备的访问方法,其中一bio 结构体最后一个是长度为0 的数组,这个有什么意义呢?
如果申请做下面的处理:
struct bio *buf;
int bio_vec_len /*缓冲区数据的长度*/
/*直接把buffer的结构体跟存放数据的内存一起分配了*/
buf = (struct bio *) malloc(sizeof(struct bio) + bio_ven_len*sizeof(struct bio_vec));
buf->bio_vec = "数据struct bio_vec data\n";
/*也可以下面这样引用:*/
buf->bio_vec = “初始化数据”; /*bio_vec data的取值范围:0~bio_vec_len-1*/
在结构体中,我们定义了0长度的数组,按理buf->bio_vec =“初始化数据”;属于越界访问,但是我们把结构体后面的n*sizeof(struct
bio_vec)个长度的空间也一起申请了,所以该访问是合法的!
结构体最后使用0或1的长度数组的原因,主要是为了方便的管理内存缓冲区,如果你直接使用指针而不使用数组,那么,你在分配内存缓冲区时,就必须分配结构体一次,然后再分配结构体内的指针一次,(而此时分配的内存已经与结构体的内存不连续了,所以要分别管理即申请和释放)而如果使用数组,那么只需要一次就可以全部分配出来,(见下面的例子),反过来,释放时也是一样,使用数组,一次释放,使用指针,得先释放结构体内的指针,再释放结构体。还不能颠倒次序。
其实就是分配一段连续的的内存,减少内存的碎片化。
example:
在Linux系统里,/usr/include/linux/if_pppox.h里面有这样一个结构:
struct pppoe_tag {
__u16 tag_type;
__u16 tag_len;
char tag_data[0];
} __attribute ((packed));
最后一个成员为可变长的数组,对于TLV(Type-Length-Value)形式的结构,或者其他需要变长度的结构体,用这种方式定义最好。使用起来非常方便,创建时,malloc一段结构体大小加上可变长数据长度的空间给它,可变长部分可按数组的方式访问,释放时,直接把整个结构体free掉就可以了。例子如下:
struct pppoe_tag *sample_tag;
__u16 sample_tag_len = 10;
sample_tag = (struct pppoe_tag *)malloc(sizeof(struct pppoe_tag)+sizeof(char)*sample_tag_len);
sample_tag->tag_type = 0xffff;
sample_tag->tag_len = sample_tag_len;
sample_tag->tag_data[0]=....
...
释放时,
free(sample_tag)
更多详细网址:
http://stackoverflow.com/questions/11733981/what-is-the-purpose-of-a-zero-length-array-in-a-struct
https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html
struct bio { sector_t bi_sector; /* 磁盘上相关扇区 */ struct bio *bi_next; /* 请求列表 */ struct block_device *bi_bdev; /* 相关的块设备 */ unsigned long bi_flags; /* 状态和命令标志 */ unsigned long bi_rw; /* 读还是写 */ unsigned short bi_vcnt; /* bio_vecs的数目 */ unsigned short bi_idx; /* bio_io_vect的当前索引 */ /* Number of segments in this BIO after * physical address coalescing is performed. * 结合后的片段数目 */ unsigned int bi_phys_segments; unsigned int bi_size; /* 剩余 I/O 计数 */ /* * To keep track of the max segment size, we account for the * sizes of the first and last mergeable segments in this bio. * 第一个和最后一个可合并的段的大小 */ unsigned int bi_seg_front_size; unsigned int bi_seg_back_size; unsigned int bi_max_vecs; /* bio_vecs数目上限 */ unsigned int bi_comp_cpu; /* 结束CPU */ atomic_t bi_cnt; /* 使用计数 */ struct bio_vec *bi_io_vec; /* bio_vec 链表 */ bio_end_io_t *bi_end_io; /* I/O 完成方法 */ void *bi_private; /* bio结构体创建者的私有方法 */ #if defined(CONFIG_BLK_DEV_INTEGRITY) struct bio_integrity_payload *bi_integrity; /* data integrity */ #endif bio_destructor_t *bi_destructor; /* bio撤销方法 */ /* * We can inline a number of vecs at the end of the bio, to avoid * double allocations for a small number of bio_vecs. This member * MUST obviously be kept at the very end of the bio. * 内嵌在结构体末尾的 bio 向量,主要为了防止出现二次申请少量的 bio_vecs */ struct bio_vec bi_inline_vecs[0]
}
如果申请做下面的处理:
struct bio *buf;
int bio_vec_len /*缓冲区数据的长度*/
/*直接把buffer的结构体跟存放数据的内存一起分配了*/
buf = (struct bio *) malloc(sizeof(struct bio) + bio_ven_len*sizeof(struct bio_vec));
buf->bio_vec = "数据struct bio_vec data\n";
/*也可以下面这样引用:*/
buf->bio_vec = “初始化数据”; /*bio_vec data的取值范围:0~bio_vec_len-1*/
在结构体中,我们定义了0长度的数组,按理buf->bio_vec =“初始化数据”;属于越界访问,但是我们把结构体后面的n*sizeof(struct
bio_vec)个长度的空间也一起申请了,所以该访问是合法的!
结构体最后使用0或1的长度数组的原因,主要是为了方便的管理内存缓冲区,如果你直接使用指针而不使用数组,那么,你在分配内存缓冲区时,就必须分配结构体一次,然后再分配结构体内的指针一次,(而此时分配的内存已经与结构体的内存不连续了,所以要分别管理即申请和释放)而如果使用数组,那么只需要一次就可以全部分配出来,(见下面的例子),反过来,释放时也是一样,使用数组,一次释放,使用指针,得先释放结构体内的指针,再释放结构体。还不能颠倒次序。
其实就是分配一段连续的的内存,减少内存的碎片化。
example:
在Linux系统里,/usr/include/linux/if_pppox.h里面有这样一个结构:
struct pppoe_tag {
__u16 tag_type;
__u16 tag_len;
char tag_data[0];
} __attribute ((packed));
最后一个成员为可变长的数组,对于TLV(Type-Length-Value)形式的结构,或者其他需要变长度的结构体,用这种方式定义最好。使用起来非常方便,创建时,malloc一段结构体大小加上可变长数据长度的空间给它,可变长部分可按数组的方式访问,释放时,直接把整个结构体free掉就可以了。例子如下:
struct pppoe_tag *sample_tag;
__u16 sample_tag_len = 10;
sample_tag = (struct pppoe_tag *)malloc(sizeof(struct pppoe_tag)+sizeof(char)*sample_tag_len);
sample_tag->tag_type = 0xffff;
sample_tag->tag_len = sample_tag_len;
sample_tag->tag_data[0]=....
...
释放时,
free(sample_tag)
更多详细网址:
http://stackoverflow.com/questions/11733981/what-is-the-purpose-of-a-zero-length-array-in-a-struct
https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html
相关文章推荐
- 理解sqlserver 锁机制
- jvm基础知识三-----基本垃圾回收算法
- Struts2笔记――9.输入校验
- 【二十五】回顾jekyll安装以及简短总结
- 2015-8-19省赛模拟总结
- cocos2dx 3.x bindings-generator(Part one)
- 求二叉树的深度和宽度平衡最大距离
- IOS支付宝集成一系列问题
- PHP 的var const static define self $this 使用详解
- iostat和iowait详细解说(转载:http://oplinux.com/order/iostat.html)
- TCP/IP协议三次握手与四次握手流程解析
- sql 左右连接 on 之后的and 和where的区别
- javascript -- 事件捕获,事件冒泡
- hdu-1869 六度分离(SPFA做法)
- 读书笔记之计算机操作系统(1)
- 骗人的是人,在意的是人
- lightoj1033 - Generating Palindromes (LCS)
- HUST 1408
- POJ 3349
- FZU1404 Andy的作业