memmove 内存映射引起崩溃问题

最近遇到一个由内存映射引起崩溃问题,因此记录一下解决方法:
一,使用gdb加载core文件,bt操作命令查看堆栈崩溃信息(当未发现core文件的时候可以通过dmesg命令工具进行排查):
在这里插入图片描述
定位错误函数代码:

bool ErrorMsgManage::WriteErrMsgToFile (unsigned long updateTime)
{
	// 加锁
	std::lock_guard<std::mutex> lkfile(m_filelock);	 
	// 获取文件指针和map错误队列
	ftruncate(fd, sizeof(sErrMsgFile)*m_ErrorMsg_map.size() + TIME_LEN) ;  
	// 从文件指针的现行位置
	lseek(fd,0,SEEK_CUR) ;  
	// 文件对象映射到进程的地址空间
	unsigned char *p_map = (unsigned char*)mmap(Null,sizeof(sErrMsgFile)*m_ErrorMsg_map,size() + TIME_LEN, PROT_READ|PROT_WRITE,MAP_SHARED,fd,0 )
	unsigned char* tmp_map = p_map;
	// 写入时间
	memmove (tmp_map, std::to_string(updateTime).c_str(), TIME_LEN) :
	tmp_map += TIME_LEN;
	// 取出错误信息,写入
	for (auto iter : m_ErrorMsg_map)
	{
		unsigned char* aa = reinterpret_cast<unsigned char*>(&iter.second) ;
		memmove (tmp_map , aa, sizeof(ErrMsgFieldInfol) ;
		tmp_map += sizeof(sErrMsgFile) ;
	}	
	// 关闭内存映射
	munmap ( p_map , sizeof(sErrMsgFile)*m_ErrorMsg_map.size() + TIME_LEN) ;
	return true;
}

崩溃行:
在这里插入图片描述
二,memmove函数:主要作用是从源内存块拷贝一定数量的字节到目标内存块,但只有在源地址和目标地址不重叠时才会拷贝数据。如果源地址和目标地址重叠,该函数会从后向前拷贝数据,以避免数据被覆盖。
三,该函数出现异常原因大致有两个:1,拷贝的内存地址非法。2,只有目标内存块的大小小于源内存块的大小,可能会导致数据被截断,造成不可预期的结果。
四,根据1排查:
a>查看内存空间,内存空间充足
在这里插入图片描述
b>经过检查引入的数据正常
c>怀疑多个地方对同一个文件进行写操作导致的,但是对文件操作是有加锁的,排除此坏一点。

std::lock_guard<std::mutex> lkfile(m_filelock);

五,根据2排查:
a>地址空间可能冲突
WriteErrMsgToFile函数中有地址空间映射操作

unsigned char *p_map = (unsigned char*)mmap(Null,sizeof(sErrMsgFile)*m_ErrorMsg_map,size() + TIME_LEN, PROT_READ|PROT_WRITE,MAP_SHARED,fd,0 )

因此怀疑读取队列大小,并映射地址空间完成之后,有操作对map队列写入数据,导致读取队列数据集大于映射出来的地址空间。
检查代码,果然发现对错误消息插入队列的时候未调用锁,而直接进行写数据的操作。代码如下:

void ErrorMsgManage::InsertErrorMsgMap(sErrMsgFile* p_ErrMsgFieldMap)
{
	sErrMsgFile *p = reinterpret_cast<sErrMsgFile>(p_ErrMsgFieldMap );
	auto iter = m_ErrorMsg_map.find(p->ErrorCode);
	if ( iter == m_ErrorMsg_map.end())
	{
		m_ErrorMsg_map.insert({p->ErrorCode,*p});
	}
}

六,解决方法:
在调用错误消息插入队列函数InsertErrorMsgMap中,进行枷锁,避免再次出现崩溃。

std::lock_guard<std::mutex> lkfile(m_filelock);

七,总结:1,确定异常代码段(看日志, 查看core文件, 查看系统日志文件syslog)
2,分析引起错误引起原因的可能性,再追一验证排查

  • 12
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值