零长数组剖析
2016-05-05 21:36
323 查看
想必在阅读内核代码中,大家经常会遇到零长数组,该语法归GUN C特有,标准C和C++都不具备该性能。出于好奇,所以通过编写代码来分析零长数组使用方法,同时用来研究零长数组的特点。
zero_array.c为研究零长数组代码,log.txt为程序运行后输出信息。为了供大家参考及体现真实性,所以将源代码和程序运行后输出的信息统一释放出来供大家参考。
-------------------------------------------------------------------------zero_array.c start------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
struct test {
int num;
char zero_array[];
};
#define NUM 255
#define MACRO_FREE
//#define MACRO_FREE_PAGE
int main(int argc, char *argv[])
{
struct test *tst = NULL;
int number = NUM;
tst = (struct test *)malloc(sizeof(struct test) + number);
tst->num = number;
tst->zero_array[0] = 'H';
tst->zero_array[1] = 'e';
tst->zero_array[2] = 'l';
tst->zero_array[3] = 'l';
tst->zero_array[4] = 'o';
tst->zero_array[5] = '\0';
printf("size = %ld\n", sizeof(struct test));
printf("tst->num = %d\n", tst->num);
printf("tst->zero_array[]:%s\n", tst->zero_array);
#if defined(MACRO_FREE)
free(tst);
#if defined(MACRO_FREE_PAGE)
free(tst->zero_array);
#endif
#else
;
#endif
printf("tst Addr: %p\n", tst);
printf("tst->num Addr:
%p\n", &tst->num);
printf("tst->zero_array[] Addr: %p\n", tst->zero_array);
printf("tst->zero_array[0] Addr: %p\n", &tst->zero_array[0]);
printf("tst->zero_array[1] Addr: %p\n", &tst->zero_array[1]);
return 0;
}
-------------------------------------------------------------------------zero_array.c end------------------------------------------------------------------------
-----------------------------------------------------------------------------log.tex start --------------------------------------------------------------------------
fanyanlai@ubuntu-virtual-machine:~/work/test$ ./zero_array
size = 4
tst->num = 255
tst->zero_array[]:Hello
tst Addr: 0x10dd010
tst->num Addr: 0x10dd010
tst->zero_array[] Addr: 0x10dd014
tst->zero_array[0] Addr: 0x10dd014
tst->zero_array[1] Addr: 0x10dd015
打开宏//#define MACRO_FREE_PAGE 后程序运行结果:
fanyanlai@ubuntu-virtual-machine:~/work/test$ ./zero_array
tst->num = 255
tst->zero_array[]:Hello
*** glibc detected *** ./zero_array: free(): invalid pointer: 0x0000000001e72014 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x7db26)[0x7ff54bc94b26]
./zero_array[0x400643]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xed)[0x7ff54bc3876d]
./zero_array[0x4004c9]
======= Memory map: ========
00400000-00401000 r-xp 00000000 08:06 19770620 /home/fanyanlai/work/test/zero_array
00600000-00601000 r--p 00000000 08:06 19770620 /home/fanyanlai/work/test/zero_array
00601000-00602000 rw-p 00001000 08:06 19770620 /home/fanyanlai/work/test/zero_array
01e72000-01e93000 rw-p 00000000 00:00 0 [heap]
7ff54ba01000-7ff54ba16000 r-xp 00000000 08:06 17043068 /lib/x86_64-linux-gnu/libgcc_s.so.1
7ff54ba16000-7ff54bc15000 ---p 00015000 08:06 17043068 /lib/x86_64-linux-gnu/libgcc_s.so.1
7ff54bc15000-7ff54bc16000 r--p 00014000 08:06 17043068 /lib/x86_64-linux-gnu/libgcc_s.so.1
7ff54bc16000-7ff54bc17000 rw-p 00015000 08:06 17043068 /lib/x86_64-linux-gnu/libgcc_s.so.1
7ff54bc17000-7ff54bdcb000 r-xp 00000000 08:06 17039495 /lib/x86_64-linux-gnu/libc-2.15.so
7ff54bdcb000-7ff54bfca000 ---p 001b4000 08:06 17039495 /lib/x86_64-linux-gnu/libc-2.15.so
7ff54bfca000-7ff54bfce000 r--p 001b3000 08:06 17039495 /lib/x86_64-linux-gnu/libc-2.15.so
7ff54bfce000-7ff54bfd0000 rw-p 001b7000 08:06 17039495 /lib/x86_64-linux-gnu/libc-2.15.so
7ff54bfd0000-7ff54bfd5000 rw-p 00000000 00:00 0
7ff54bfd5000-7ff54bff7000 r-xp 00000000 08:06 17039488 /lib/x86_64-linux-gnu/ld-2.15.so
7ff54c1d9000-7ff54c1dc000 rw-p 00000000 00:00 0
7ff54c1f3000-7ff54c1f7000 rw-p 00000000 00:00 0
7ff54c1f7000-7ff54c1f8000 r--p 00022000 08:06 17039488 /lib/x86_64-linux-gnu/ld-2.15.so
7ff54c1f8000-7ff54c1fa000 rw-p 00023000 08:06 17039488 /lib/x86_64-linux-gnu/ld-2.15.so
7fff509b9000-7fff509da000 rw-p 00000000 00:00 0 [stack]
7fff509ff000-7fff50a00000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
Aborted (core dumped)
-----------------------------------------------------------------------------log.tex end-----------------------------------------------------------------------------
一、零长数组优点?
1)节省空间
如果指定数组大小,当定义包含数组元素的结构体变量时,系统不但会为结构体中其它变量分配内存,同时
也会为该数组分配内存。
如果不指定数组大小(零长数组),当定义包含数组元素的结构体变量时,系统只会为结构体中其它变量分配内存,不会
为零长数组分配内存。
如代码所示:printf("size = %ld\n", sizeof(struct test));
运行程序,输出信息中:size = 4;//表明零长数组不占内存,4字节恰好为int类型变量所占内存大小。
2)灵活性
根据需要动态分配该数组长度(动态内存长度)。
如代码所示,tst = (struct test *)malloc(sizeof(struct test) + number);//为零长数组分配255字节内存。
紧接着初始化内存:
tst->zero_array[0] = 'H';
tst->zero_array[1] = 'e';
tst->zero_array[2] = 'l';
tst->zero_array[3] = 'l';
tst->zero_array[4] = 'o';
tst->zero_array[5] = '\0';
输出字符串:
printf("tst->zero_array[]:%s\n", tst->zero_array);
运行程序:
tst->zero_array[]:Hello
二、malloc动态分配内存
查看动态分配内存后结构体变量及其内部元素内部分配情况:
如代码所示:
printf("tst Addr: %p\n", tst);
printf("tst->num Addr:
%p\n", &tst->num);
printf("tst->zero_array[] Addr: %p\n", tst->zero_array);
printf("tst->zero_array[0] Addr: %p\n", &tst->zero_array[0]);
printf("tst->zero_array[1] Addr: %p\n", &tst->zero_array[1]);
运行程序:
tst Addr: 0x10dd010
tst->num Addr:
0x10dd010
tst->zero_array[] Addr: 0x10dd014
tst->zero_array[0] Addr: 0x10dd014
tst->zero_array[1] Addr: 0x10dd015
分析:零长数组与num元素刚好相差4个字节。
三、free释放内存
动态分配的内存,在用完之后,需要用free显示释放,以免造成内存泄露。
将代码中//#define MACRO_FREE_PAGE 宏打开。
运行程序:
fanyanlai@ubuntu-virtual-machine:~/work/test$ ./zero_array
tst->num = 255
tst->zero_array[]:Hello
*** glibc detected *** ./zero_array: free(): invalid pointer: 0x0000000001e72014
***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x7db26)[0x7ff54bc94b26]
./zero_array[0x400643]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xed)[0x7ff54bc3876d]
./zero_array[0x4004c9]
Aborted (core dumped)
出现invalid pointer错误,说明释放动态内存成功。
注意:对于动态malloc(kmalloc)分配内存,需要用free(kfree)释放,养成编程好习惯。
zero_array.c为研究零长数组代码,log.txt为程序运行后输出信息。为了供大家参考及体现真实性,所以将源代码和程序运行后输出的信息统一释放出来供大家参考。
-------------------------------------------------------------------------zero_array.c start------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
struct test {
int num;
char zero_array[];
};
#define NUM 255
#define MACRO_FREE
//#define MACRO_FREE_PAGE
int main(int argc, char *argv[])
{
struct test *tst = NULL;
int number = NUM;
tst = (struct test *)malloc(sizeof(struct test) + number);
tst->num = number;
tst->zero_array[0] = 'H';
tst->zero_array[1] = 'e';
tst->zero_array[2] = 'l';
tst->zero_array[3] = 'l';
tst->zero_array[4] = 'o';
tst->zero_array[5] = '\0';
printf("size = %ld\n", sizeof(struct test));
printf("tst->num = %d\n", tst->num);
printf("tst->zero_array[]:%s\n", tst->zero_array);
#if defined(MACRO_FREE)
free(tst);
#if defined(MACRO_FREE_PAGE)
free(tst->zero_array);
#endif
#else
;
#endif
printf("tst Addr: %p\n", tst);
printf("tst->num Addr:
%p\n", &tst->num);
printf("tst->zero_array[] Addr: %p\n", tst->zero_array);
printf("tst->zero_array[0] Addr: %p\n", &tst->zero_array[0]);
printf("tst->zero_array[1] Addr: %p\n", &tst->zero_array[1]);
return 0;
}
-------------------------------------------------------------------------zero_array.c end------------------------------------------------------------------------
-----------------------------------------------------------------------------log.tex start --------------------------------------------------------------------------
fanyanlai@ubuntu-virtual-machine:~/work/test$ ./zero_array
size = 4
tst->num = 255
tst->zero_array[]:Hello
tst Addr: 0x10dd010
tst->num Addr: 0x10dd010
tst->zero_array[] Addr: 0x10dd014
tst->zero_array[0] Addr: 0x10dd014
tst->zero_array[1] Addr: 0x10dd015
打开宏//#define MACRO_FREE_PAGE 后程序运行结果:
fanyanlai@ubuntu-virtual-machine:~/work/test$ ./zero_array
tst->num = 255
tst->zero_array[]:Hello
*** glibc detected *** ./zero_array: free(): invalid pointer: 0x0000000001e72014 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x7db26)[0x7ff54bc94b26]
./zero_array[0x400643]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xed)[0x7ff54bc3876d]
./zero_array[0x4004c9]
======= Memory map: ========
00400000-00401000 r-xp 00000000 08:06 19770620 /home/fanyanlai/work/test/zero_array
00600000-00601000 r--p 00000000 08:06 19770620 /home/fanyanlai/work/test/zero_array
00601000-00602000 rw-p 00001000 08:06 19770620 /home/fanyanlai/work/test/zero_array
01e72000-01e93000 rw-p 00000000 00:00 0 [heap]
7ff54ba01000-7ff54ba16000 r-xp 00000000 08:06 17043068 /lib/x86_64-linux-gnu/libgcc_s.so.1
7ff54ba16000-7ff54bc15000 ---p 00015000 08:06 17043068 /lib/x86_64-linux-gnu/libgcc_s.so.1
7ff54bc15000-7ff54bc16000 r--p 00014000 08:06 17043068 /lib/x86_64-linux-gnu/libgcc_s.so.1
7ff54bc16000-7ff54bc17000 rw-p 00015000 08:06 17043068 /lib/x86_64-linux-gnu/libgcc_s.so.1
7ff54bc17000-7ff54bdcb000 r-xp 00000000 08:06 17039495 /lib/x86_64-linux-gnu/libc-2.15.so
7ff54bdcb000-7ff54bfca000 ---p 001b4000 08:06 17039495 /lib/x86_64-linux-gnu/libc-2.15.so
7ff54bfca000-7ff54bfce000 r--p 001b3000 08:06 17039495 /lib/x86_64-linux-gnu/libc-2.15.so
7ff54bfce000-7ff54bfd0000 rw-p 001b7000 08:06 17039495 /lib/x86_64-linux-gnu/libc-2.15.so
7ff54bfd0000-7ff54bfd5000 rw-p 00000000 00:00 0
7ff54bfd5000-7ff54bff7000 r-xp 00000000 08:06 17039488 /lib/x86_64-linux-gnu/ld-2.15.so
7ff54c1d9000-7ff54c1dc000 rw-p 00000000 00:00 0
7ff54c1f3000-7ff54c1f7000 rw-p 00000000 00:00 0
7ff54c1f7000-7ff54c1f8000 r--p 00022000 08:06 17039488 /lib/x86_64-linux-gnu/ld-2.15.so
7ff54c1f8000-7ff54c1fa000 rw-p 00023000 08:06 17039488 /lib/x86_64-linux-gnu/ld-2.15.so
7fff509b9000-7fff509da000 rw-p 00000000 00:00 0 [stack]
7fff509ff000-7fff50a00000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
Aborted (core dumped)
-----------------------------------------------------------------------------log.tex end-----------------------------------------------------------------------------
一、零长数组优点?
1)节省空间
如果指定数组大小,当定义包含数组元素的结构体变量时,系统不但会为结构体中其它变量分配内存,同时
也会为该数组分配内存。
如果不指定数组大小(零长数组),当定义包含数组元素的结构体变量时,系统只会为结构体中其它变量分配内存,不会
为零长数组分配内存。
如代码所示:printf("size = %ld\n", sizeof(struct test));
运行程序,输出信息中:size = 4;//表明零长数组不占内存,4字节恰好为int类型变量所占内存大小。
2)灵活性
根据需要动态分配该数组长度(动态内存长度)。
如代码所示,tst = (struct test *)malloc(sizeof(struct test) + number);//为零长数组分配255字节内存。
紧接着初始化内存:
tst->zero_array[0] = 'H';
tst->zero_array[1] = 'e';
tst->zero_array[2] = 'l';
tst->zero_array[3] = 'l';
tst->zero_array[4] = 'o';
tst->zero_array[5] = '\0';
输出字符串:
printf("tst->zero_array[]:%s\n", tst->zero_array);
运行程序:
tst->zero_array[]:Hello
二、malloc动态分配内存
查看动态分配内存后结构体变量及其内部元素内部分配情况:
如代码所示:
printf("tst Addr: %p\n", tst);
printf("tst->num Addr:
%p\n", &tst->num);
printf("tst->zero_array[] Addr: %p\n", tst->zero_array);
printf("tst->zero_array[0] Addr: %p\n", &tst->zero_array[0]);
printf("tst->zero_array[1] Addr: %p\n", &tst->zero_array[1]);
运行程序:
tst Addr: 0x10dd010
tst->num Addr:
0x10dd010
tst->zero_array[] Addr: 0x10dd014
tst->zero_array[0] Addr: 0x10dd014
tst->zero_array[1] Addr: 0x10dd015
分析:零长数组与num元素刚好相差4个字节。
三、free释放内存
动态分配的内存,在用完之后,需要用free显示释放,以免造成内存泄露。
将代码中//#define MACRO_FREE_PAGE 宏打开。
运行程序:
fanyanlai@ubuntu-virtual-machine:~/work/test$ ./zero_array
tst->num = 255
tst->zero_array[]:Hello
*** glibc detected *** ./zero_array: free(): invalid pointer: 0x0000000001e72014
***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x7db26)[0x7ff54bc94b26]
./zero_array[0x400643]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xed)[0x7ff54bc3876d]
./zero_array[0x4004c9]
Aborted (core dumped)
出现invalid pointer错误,说明释放动态内存成功。
注意:对于动态malloc(kmalloc)分配内存,需要用free(kfree)释放,养成编程好习惯。
相关文章推荐
- (OK) running CORE & docker on Fedora 23 server - all commands
- 微软认证系统工程师MCSE
- 从头认识多线程-2.11 synchronized标记的方法和synchronized(this)标记的代码块锁定的是当前对象
- [CareerCup] 18.5 Shortest Distance between Two Words 两单词间的最短距离
- poj 2002(好题 链式hash+已知正方形两点求另外两点)
- redis底层数据结构之intset
- Redis主从自动failover
- 职业规划第五次作业
- Redis主从自动failover
- poj 1064 Cable master
- 把二叉树打印成多行
- 大数据学习笔记·社会计算(3)
- linux下ssh客户端命令远程登入系统详解
- Spring Web MVC架构
- "https://open.gl/"教程之Textures源码(freeglut版)
- Unity3D 3D坦克大战
- 谷歌chrome浏览器和火狐firefox浏览器自带http抓包工具和请求模拟插件
- python自动化脚本ftp应用
- BigInteger、BigDecimal、数字格式化
- 基于Netbeans的安卓Android开发环境配置