std::list什么情况下会出现error的错误?

red-fly red-fly 墨衍会员 · AI 创作全网分发 墨衍智能分发 通过墨衍一键同步至各平台 可同步平台 CSDN微信公众号微博知乎掘金百家号博客园抖音小红书 你的文章也可以这样分发 墨衍会员 ¥399起/年,写一次发全网 我也要 + 加入社区
为了对内存的管理,使用了std模板,定义了两个变量:

map<int, mem_s_info> m_mapMemBusyList; // 正在使用的内存列表,key为内存地址
list<mem_s_info> m_vecMemFreeList;

m_mapMemBusyList用来保存正在使用的内存,m_vecMemFreeList保存未被使用的内存。
其中结构mem_s_info定义如下(这个结构本身可以不用去关心它):

struct mem_s_info
{
char *pszBuf; // 内存地址
int len; // 内存长度
int id; // 内存的标示号,暂时没什么用处
__time64_t ttCreate; // 创建时间
__time64_t ttAccess; // 最后一次访问时间,即被重新利用的时间

#ifdef _DEBUG
mem_ins_info memIns; // 用于保存分配该内存的代码信息
#endif
};

流程如下:
在要分配一个内存时,首先从m_vecMemFreeList中查找是否有对应长度的空闲内存,如果有,就把它从m_vecMemFreeList中移到m_mapMemBusyList中,如果没有,则分配一个新的,然后加入到m_mapMemBusyList中。代码如下:

char *CMemoryManagerS::CreateMem( const int len, const char* file /*= NULL*/, const char *function /*= NULL*/, const int line /*= 0*/ )
{
if ( len < 0 || len > 0x4000000 )
return NULL;

// 如果为0,则也分配8个字节
int startlen = len;
if ( len == 0 )
startlen = 1;

mem_s_info *pstuSInfo;
char *pReturnPtr = NULL;
list<mem_s_info>::iterator iterFree;
CAutoCri criFree( m_csMemBusy);
for ( iterFree = m_vecMemFreeList.begin(); iterFree != m_vecMemFreeList.end(); iterFree++ )
{
pstuSInfo = &(*iterFree);
if ( pstuSInfo->len <= startlen )
continue;

if ( pstuSInfo->len > startlen * 5/4 && pstuSInfo->len >= 32 )
{
// 比需求内存大的最小内存,比需求内存大了1/4,所以为了节约,重新进行申请,防止过分地浪费内存。
break;
}

// 搞定
pstuSInfo->ttAccess = _time64(NULL);
memset( pstuSInfo->pszBuf, 0, pstuSInfo->len );

// 把此条记录移到使用列表中
pReturnPtr = pstuSInfo->pszBuf;
#ifdef _DEBUG
SetMemIns( pstuSInfo, file, function, line );
#endif
m_mapMemBusyList[(int)pReturnPtr] = *pstuSInfo;
m_vecMemFreeList.erase( iterFree );
return pReturnPtr;
}
criFree.Release();

// 需要分配新的内存。弄成8字节对齐,估计运行的效率会高一些
int irelen = startlen + 8; // 不是+7,目的是要使分配出来的内存一定比实际指定的要大,最多大8个字节,最少大1个字节
irelen /= 8;
irelen *= 8;

mem_s_info stuSInfo;
stuSInfo.pszBuf = new char[irelen];
stuSInfo.len = irelen;

CAutoCri criCounter( m_csIDCounter );
stuSInfo.id = m_memIDCounter++;
criCounter.Release();

stuSInfo.ttCreate = _time64(NULL);
stuSInfo.ttAccess = stuSInfo.ttCreate;
if ( stuSInfo.pszBuf == NULL )
{
return NULL; // 分配失败
}

memset( stuSInfo.pszBuf, 0, stuSInfo.len );
#ifdef _DEBUG
SetMemIns( &stuSInfo, file, function, line );
#endif
CAutoCri criBusy2( m_csMemBusy );
m_mapMemBusyList[(int)stuSInfo.pszBuf] = stuSInfo;
criBusy2.Release();

return stuSInfo.pszBuf;
}


在删除时,直接把要删除的从m_mapMemBusyList中移到m_vecMemFreeList中即可,代码如下:

UINT32 CMemoryManagerS::DeleteMem( const char *pmemAddress )
{
map<int, mem_s_info>::iterator iter;
list<mem_s_info>::iterator iterFree;
mem_s_info memInfo = {0};

CAutoCri criBusy( m_csMemBusy);
iter = m_mapMemBusyList.find( (int)pmemAddress );
if ( iter == m_mapMemBusyList.end() )
{
return errorcode_MEM_DELETEALREADY;
}

// 把它从使用表中移到未使用的列表中,并修改访问时间
memInfo = iter->second;
memInfo.ttAccess = _time64(NULL);
m_mapMemBusyList.erase( iter );
cntBusy = m_mapMemBusyList.size();

// 注意,必需先使用,然后再删除。注意必需按照从小到大的顺序插入进去

iterFree = m_vecMemFreeList.begin();
while ( iterFree != m_vecMemFreeList.end() )
{
if ( iterFree->len < memInfo.len )
{
iterFree++;
continue;
}
break;
}
m_vecMemFreeList.insert( iterFree, memInfo );

criBusy.Release();
ShinkList(); // 这一行用于删除m_vecMemFreeList中停留时间过长的那些内存,在出问题时此代码未生效,所以本贴说的问题和此函数无关
return errorcode_SUCCESS;
}


环境:vs2010,所以在变量窗口中可以看到ma和list的各项状态,正常情况如下:

m_vecMemFreeList [0] 结构mem_s_info的各字段值
[1] 结构mem_s_info的各字段值
[2] 结构mem_s_info的各字段值
[3] 结构mem_s_info的各字段值
... ...


失败时如下的形式:

m_vecMemFreeList [0] 结构mem_s_info的各字段值
[1] 结构mem_s_info的各字段值
[2] 结构mem_s_info的各字段值
[error]
[error]
[error]
... ...

注意,实际的数量有很多,即那些error都是在m_vecMemFreeList的有效个数以内。
初步认为很可能是内存越界导致的,但还不确定
大伙帮忙看下是什么问题导致的,如何定位这种问题
...全文

相关推荐

评论 7
收藏 已收藏
分享
返回顶部
red-fly
VC/MFC 16,550 成员 421,606 内容