内存释放失败问题

内存释放失败问题

  • 最近在MCU上使用内存去存储图片数据时出现内存释放失败的问题,导致内存资源一直在占用,后面定位发现了问题,故记录一下。

1.现象及原因

  • 现象:为存储拍得的图像数据,使用malloc在堆内申请了两块内存空间。一块用于存储源图片数据,一块用于保存二维化后的灰度图片数据,在使用结束后发现申请的内存释放失败,导致后面程序申请不到新的内存。

使用的大致流程如下:

unsigned char *yuv_data = NULL;
unsigned char *binar_y_data = NULL;
char ret = 0;
yuv_data = (unsigned char *)malloc(sizeof(unsigned char)640 * 480 * 3);
if(yuv_data == NULL) {
	printf("yuv_data malloc fail");
	return -1;
}
binar_y_data = (unsigned char *)malloc(sizeof(unsigned char)640 * 480);
if(binar_y_data == NULL) {
	printf("binar_y_data malloc fail");
	return -1;
}
//获取图片数据,存于内存中,格式为YUV444
ret = get_camera_data(yuv_data);
if(ret != 0) {
	printf("get camera data fail");
	return -1;
}
//得到图片数据提取Y值,然后二值化处理,并将二值化后的数据打印
ret = binary_data(binar_y_data,yuv_data,(640 * 480 * 3));
if(ret != 0) {
	printf("get binary data fail");
	return -1;
}
printf("printf binary data start\n\r");
for(int i = 0 ; i < (640*480) ;i++) {
	printf("0x%02x  ",*(binar_y_data++));
}
printf("printf binary data end\n\r");

free(binar_y_data);//该处报错
free(yuv_data);

在释放binar_y_data这块内存时,打印报出释放失败,后定位,发现由于遗漏没有在打印二值化数据之前备份这块内存的首地址,导致内存释放失败
解决方法是:将malloc得到的内存首地址保存起来,释放时传入得到的这块内存首地址即可

unsigned char *bak_addr = NULL;
bak_addr = binar_y_data;
printf("printf binary data start\n\r");
for(int i = 0 ; i < (640*480) ;i++) {
	printf("0x%02x  ",*(binar_y_data++));
}
printf("printf binary data end\n\r");
binar_y_data = bak_addr;
free(binar_y_data);//该处报错
free(yuv_data);

这时内存就可以正常释放了,原因就是疏忽了malloc和free的用法,使用free函数时,传参需是在malloc时获取的空间地址,至于为什么这样后面会说到;可能很多朋友也是只知道使用malloc和free,没有关注实现的细节,故而踩坑。

2.malloc和free

具体实现详情可见网友的这篇文章malloc和free源代码实现

  • 在申请内存时实际分配的空间分为空间头和空间体,空间体才是我们真正用来存储数据的地方,空间头是记录空间体的相关信息,包含当前这块内存的已用空间、剩余空间、指向下一块内存的指针等信息,用于管理内存的。
  • 实际使用malloc时返回的是空间体的首地址,而在释放内存时,可以看见free函数中会根据传入的地址,回退找到空间头,将该空间体的内存属性改为可用,从而实现释放操作

void free(void* ap)
{
     Header *bp,*p,*prev;
     bp=(Header*)ap-1;
     for(prev=memptr,p=memptr->s.next;
     (p!=bp) && (p!=memptr);prev=p,p=p->next);
     if(p!=bp) return;
     prev->s.freesize+=p->s.usedsize+p->s.freesize;
     prev->s.next=p->s.next;
     memptr=prev;
}
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
你好!对于Linux共享内存通信失败问题,可以尝试以下排查步骤: 1. 检查共享内存的创建和附加过程: - 确保共享内存的创建者和用户进程都使用相同的key和权限。 - 检查共享内存的创建代码,确认是否正确设置了共享内存的大小和标志。 - 确保共享内存的创建者成功创建了共享内存并返回了有效的共享内存标识符。 - 检查用户进程是否成功调用了共享内存的附加函数,并返回了有效的共享内存地址。 2. 检查进程间通信的同步机制: - 在读写共享内存之前,确保进程间已经正确进行了同步,避免竞争条件。 - 使用信号量、互斥锁或其他同步机制进行进程间同步。 3. 检查共享内存的权限和访问控制: - 确保创建共享内存的进程和用户进程都具有足够的权限访问共享内存。 - 检查文件系统或操作系统的限制,确保没有禁止或限制对共享内存的访问。 4. 检查共享内存的清理和销毁: - 确保在不再使用共享内存时,及时进行清理和销毁,避免资源泄漏。 - 在共享内存不再需要时,调用相应的函数进行释放和销毁。 5. 检查错误处理和日志记录: - 检查代码中是否正确处理了共享内存操作的错误情况。 - 在代码中添加适当的错误处理和日志记录,以便排查问题时能够获取相关信息。 希望以上提供的步骤能够帮助你解决Linux共享内存通信失败问题。如果还有其他疑问,请随时提出。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值