结构体中指针成员的动态分配
2017-05-19 11:45
232 查看
示例1:
运行结果正常。
结构体A占据的内存空间是8字节(32Bit操作系统),int型变量和char型变量各占据4字节,strlen(ptr)等于11字节,所以malloc分配的空间是20字节,分配出来的空间是地址连续的堆空间。执行memcpy()时候,ptr字符串内容会覆盖结构体中dat数组变量的起始空间,而后续的空间又有(strlen(ptr) + 1)大小,所以运行正常。
示例2:
如果把结果体A中的数组变量dat改成指针变量*dat呢,
显然,运行后发生Segmentation fault。这是因为malloc是在堆内存分配空间的,堆上的数据默认是0,也就是说指针变量默认是NULL。
在malloc之后打印结构体A的首地址以及type、dat的地址:
运行:
memcpy()函数访问的目标地址是0地址处,所以自然段错误。
如何修改,显然需要将a->dat指针指向一个合适的地方去。指向a->type之后的地址?
运行结果还是段错误:
memcpy()操作的目的地址是0x8b4d00c,而结构体变量a的起始地址,也就是a结构体首个变量type的地址0x8b4d008,其中偏移4字节,跟前面示例1对比,看似并没什么问题,但是注意,示例1中a->type之后是一个数组变量,而在本例中,a->type之后是一个指针变量,它原指向NULL,经这么修改,它指向的是自己的地址了。指针变量也是变量,它的存在本身也需要地址存放,每个指针都需要占据空间给自己用,memcpy()函数的是dat指针给自己生存用的地址,因此出现段错误。应修改为:
也就是说a->dat指向A之外的内存大小为strlen(ptr) + 1空间的起始地址,这样就可以正常运行。
typedef struct _a{ int type; char dat[1]; }A; int main(void) { char* ptr = "hello_world"; A *a = malloc(sizeof(A) + strlen(ptr) + 1); memcpy(a->dat, ptr, strlen(ptr) + 1); printf("a->dat = %s\n", a->dat); free(a); return 0; }
运行结果正常。
结构体A占据的内存空间是8字节(32Bit操作系统),int型变量和char型变量各占据4字节,strlen(ptr)等于11字节,所以malloc分配的空间是20字节,分配出来的空间是地址连续的堆空间。执行memcpy()时候,ptr字符串内容会覆盖结构体中dat数组变量的起始空间,而后续的空间又有(strlen(ptr) + 1)大小,所以运行正常。
示例2:
如果把结果体A中的数组变量dat改成指针变量*dat呢,
typedef struct _a{ int type; char *dat; }A; int main(void) { char* ptr = "hello_world"; A *a = malloc(sizeof(A) + strlen(ptr) + 1); memcpy(a->dat, ptr, strlen(ptr) + 1); printf("a->dat = %s\n", a->dat); free(a); return 0; }
显然,运行后发生Segmentation fault。这是因为malloc是在堆内存分配空间的,堆上的数据默认是0,也就是说指针变量默认是NULL。
在malloc之后打印结构体A的首地址以及type、dat的地址:
printf("a = %p, 4000 &a->type = %p, a->dat = %p\n", a, &a->type, a->dat);
运行:
memcpy()函数访问的目标地址是0地址处,所以自然段错误。
如何修改,显然需要将a->dat指针指向一个合适的地方去。指向a->type之后的地址?
int mian() { char* ptr = "hello_world"; A *a = malloc(sizeof(A) + strlen(ptr) + 1); printf("a = %p, &a->type = %p, a->dat = %p\n", a, &a->type, a->dat); a->dat = (char* )(&(a->type) + 1); //加1加的是步长,等价于加偏移4字节地址 printf("a->dat = %p\n", a->dat); memcpy(a->dat, ptr, strlen(ptr) + 1); printf("a->dat = %s\n", a->dat); free(a); }
运行结果还是段错误:
memcpy()操作的目的地址是0x8b4d00c,而结构体变量a的起始地址,也就是a结构体首个变量type的地址0x8b4d008,其中偏移4字节,跟前面示例1对比,看似并没什么问题,但是注意,示例1中a->type之后是一个数组变量,而在本例中,a->type之后是一个指针变量,它原指向NULL,经这么修改,它指向的是自己的地址了。指针变量也是变量,它的存在本身也需要地址存放,每个指针都需要占据空间给自己用,memcpy()函数的是dat指针给自己生存用的地址,因此出现段错误。应修改为:
a->dat = (char* )(a + 1);
也就是说a->dat指向A之外的内存大小为strlen(ptr) + 1空间的起始地址,这样就可以正常运行。
相关文章推荐
- C语言——指针与结构体 内存的动态分配
- 结构体指针为分配内存访问结构体成员错误
- typedef_结构体指针_动态分配_void*
- 关于C++中结构体及其指针成员的内存分配和释放
- C语言——指针与结构体 内存的动态分配
- C\C++中结构体变量与结构体指针内存分配问题
- Delphi 的内存操作函数(3): 给结构体指针分配内存
- 静态成员函数、this指针、对象指针和动态对象使用小结
- Delphi 调用 c编写的动态链接库,结构体指针作为参数
- C和指针之动态内存分配malloc、calloc、realloc简单使用和区别
- 如何通过offsetof 动态的给结构体或者类成员变量赋值
- C++防灾——为指针成员分配专门的存储空间
- 类和动态内存分配,类成员的动态内存分配,new,delete,定位new
- Delphi 给结构体指针分配内存,用new(p),释放用dispose(p)
- 当结构体中有指针成员时
- 包含双重指针的结构体指针的分配内存与释放内存
- 二维数组,二维数组的动态分配,以及向数组指针&指针数组的延伸
- 【VS开发】【编程开发】【C/C++开发】结构体中的数组与指针的内存分配情况说明
- 结构体中最后成员为一个数组(长度为零)与一个指针
- 指针作数据成员建立动态数组