项目场景:
承接上级消息,消息中有一个二级指针**mbr,我想要实现自己申请一个一样的二级指针记录改数据传下来的值。
模型为:表示有cnt个lib_info_t结构体。
typedef struct {
int32_t a;
int32_t b;
} lib_info_t;
typedef struct {
int cnt;
lib_info_t **mbr;
} mbr_info_t;
mbr_info_t dest;
mbr_info_t src;
问题描述
程序老是出现莫名奇妙的cord dump,或者赋值异常,排查一天才发现问题原因。
原因分析:
1、malloc问题
二级指针malloc的申请,首先要申请二级指针的内存。
dest->mbr= (lib_info_t **)malloc(src->cnt * sizeof(lib_info_t **));
if (dest->mbr== NULL ) {
return E_MEMORY;
}
此处申请几个,和几个结构体有关,而不是之前想的一次把内存全部申请上,像下面这样是会踩坑的,二级指针只是一个指向指针的值,一般不直接给到结构体数组的内存,需要给结构体数组的指针,上面的申请,每一个(lib_info_t **)内存解引用后,都可以指向结构体的首地址,所以表示申请了一串可以指向结构体地址的指针地址。
**范例:**
dest->mbr= (lib_info_t **)malloc(src->cnt * sizeof(lib_info_t ));
申请了可以指向结构体地址的指针后,再申请结构体内存,此处应该是1个,类似二位数组的a[n][1],这样就把二维指针和结构体指针串起来了。
for (i = 0;i < src->cnt; i++) {
dest->mbr[i] = (lib_info_t *)malloc( sizeof(lib_info_t ));
if (dest->mbr[i] == NULL ) {
for (i = i-1 ;i >= 0; i--) {
free(dest->mbr[i]);
}
free(dest->mbr);
return E_MEMORY;
}
}
此处类似a[n][m]模型同理。。。之前就搞错顺序了,写成a[1][n],还傻傻的用a[i]去copy,切记不能这样干!,下面这样是错的!!
**错误范例:**
dest->mbr= (lib_info_t **)malloc(sizeof(lib_info_t **));
if (dest->mbr== NULL ) {
return E_MEMORY;
}
*dest->mbr= (lib_info_t *)malloc( src->cnt * sizeof(lib_info_t ));
if (*dest->mbr== NULL ) {
return E_MEMORY;
}
2、memcpy问题
由于之前的结构体内存是每个都malloc的,可想而知。。。。,如果有人有好的方法,请一定要在评论中和我说!!
for (i = 0;i < src->lib_info.mbr_cnt; i++) {
printf("memcpy %p %p\n",dest->mbr[i], src->mbr[i]);
memcpy(dest->mbr[i], src->mbr[i], sizeof(lib_info_t ));
}
解决方案:
以上就是分析和解决的举例。
其实我隐约觉的还有更好的解,就是明明可以申请一块大内存,直接将整个结构体数组装下的那种,是不是就可以直接memcpy呢,类似
int a[n][1] = (int **)malloc(sizeof(int) *n *1));
memset(a, 0 ,(sizeof(int) *n *1) )
但这样用的前提是上面传下来的就是这样申请的整块,要是像我一样,单独每个都malloc,就G了。。。
最后------------------------->
你猜的没错!我每个错误都犯了!!!!!!