一、前言
在实际系统中,用户知道发生了什么事件的流程可能是:底层驱动检测到事件——上抛到对应模块处理——弹窗或者其他方式让用户可见。但是事件很多种,有时候不能确认事件中某一个字段值的长度,而直接申请最大长度的话,如果很大的话比较浪费内存空间。因此可能会使用下面的方式定义事件的相关信息:
typedef struct
{
...
uint64_t reserved1; //预留
uint64_t reserved2; //预留
uint32_t info_size;
uint8_t event_info[0];
}REVENT_INFO,*PREVENT_INFO;
event_info字段是不定长度的。这种情况下,不管是设置值还是获取值,我们都需要申请对应大小的空间,如果
memcpy(event->event_info, pEventInfo, nLen);
除非没有其他调用使用到这块内存,否则可能发现意料之外的问题。
二、处理
鉴于以上说明,不管是设置还是获取,我们最好都先申请一块内存,用来保存事件的信息。
以下流程以设置为例进行说明。
1、申请内存空间
CString strEventInfo = Dlg.m_strEventInfo;
CStringA strData(strEventInfo);
int nLen = strData.GetLength(); //调用输入的内容长度
int nEventInfoSize = sizeof(REVENT_INFO) + nLen;
char* pEventInfo = new(std::nothrow) char[nEventInfoSize + 1];
if (NULL == pEventInfo)
{
return ;
}
ZeroMemory(pEventInfo, nEventInfoSize + 1);
PREVENT_INFO pEvent = (PREVENT_INFO )pEventInfo;
const char* pInfo = strData.GetString();
memcpy(pEvent->event_info, pInfo, nLen);
pEvent->info_size = nLen;
...
delete[] pEvent;
pEvent = NULL;
这里为什么将CString转为CStringA呢?当用户输入的内容包含中文或者其他字符时,保证能正确设置内容;如果不转的话,字符串中含有中文等,非英文字符的情况下,可能用户设置的值和真实设置的值不一致,因为中文字符和英文字符的字节长度不一致。
因为pEvent的内存是new出来,因此在使用完了之后,最好使用delete释放掉,若不释放的话,在频繁调用情况,内存增长很快,到一定情况下,可能导致其他调用申请内存空间失败。