当遇到内存被踩问题时,如何去分析呢?
- 方法1:使用ASAN版本来打,具体方法可以参考:高通平台如何打开HWASAN
- 方法2:将被踩的这块内存保护起来,设置为ready only
通过mprotect定位谁在踩这块内存
下面重点介绍下方法2的具体实现,假设CSLMessage这个结构体里面的某个成员变量值被踩了。
第1步:申请以Page(4KB)对齐的一块Buffer
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
#include <sys/mman.h>
CSLMessage * pNewCSLMessage;
int pagesize = sysconf(_SC_PAGE_SIZE);
char * buffer = NULL;
if (pagesize == -1) {
CAMX_LOG_ERROR(CamxLogGroupCSL, "xxxxxx sysconf failed");
return result;
}
buffer = (char *)memalign(pagesize, sizeof(CSLMessage));
pNewCSLMessage = reinterpret_cast<CSLMessage *>(buffer);
第2步:对CSLMessage进行修改,然后通过mprotect将CSLMessage设置为只读
pNewCSLMessage->type = CSLMessageTypeFrame;
pNewCSLMessage->message.frameMessage.requestID = pMessage->u.frame_msg.request_id;
pNewCSLMessage->message.frameMessage.frameCount = pMessage->u.frame_msg.frame_id;
pNewCSLMessage->message.frameMessage.timestamp = pMessage->u.frame_msg.timestamp;
pNewCSLMessage->message.frameMessage.link_hdl = pMessage->u.frame_msg.link_hdl;
pNewCSLMessage->message.frameMessage.timestampType = CSLTimestampTypeMono;
pNewCSLMessage->message.frameMessage.bNotify = TRUE;
if (mprotect(buffer, pagesize, PROT_READ) == -1)
{
CAMX_LOG_ERROR(CamxLogGroupCSL, "xxxxxx set one page as read only failed;");
}
// 如果要修改为可读写,则执行下面的代码
// if (mprotect(buffer, pagesize, PROT_READ|PROT_WRITE) == -1) {
// CAMX_LOG_ERROR(CamxLogGroupCSL, "xxxxxx set one page as write prot failed;");
//}
这样就将CSLMessage这块buffer保护起来了,当有人来修改CSLMessage buffer的内容时会直接发生异常,通过异常我们就可以定位是谁在踩这块内存。
CPU 缓存导致的数据的不一致性
有时候,通过HWASAN或mprotect方法还是无法定位到是谁对某个变量进行修改了,这时候可以考虑是否是因为CPU 缓存导致的数据不一致,可以尝试用volatile
来修饰该变量,如:
volatile CSLMessage * pNewCSLMessage;
关于volatile的说明,请参阅:C语言 volatile 这篇文章。