(Windbg调试五)C++内存越界导致的std::map异常

您所在的位置:网站首页 pr如何修正视频抖动的视频 (Windbg调试五)C++内存越界导致的std::map异常

(Windbg调试五)C++内存越界导致的std::map异常

2023-12-11 06:03| 来源: 网络整理| 查看: 265

C++内存越界导致的std::map异常      前段时间在定位一个程序崩溃的问题,虽然有dump文件,能够看到出问题的具体代码行数,问题都出在同一个map上。      dump1显示map下标插入数据时异常。 在这里插入图片描述      dump2显示调用map的clear函数异常。 在这里插入图片描述      刚开始看到这两个dump,以为是多线程导致的访问冲突,看具体的代码发现对这个map的插入和删除操作是在同一个线程中的,所以排除这个可能,这时想到了另一种情况:程序中其他地方内存异常导致的程序崩溃,虽然表现在这个map对象处,但实际并不是由map引起的。因此对这个map对象所在类的所有成员变量进行一个个地排查,着重看char数组是否在调用strcpy或者memcpy时存在越界的情况,最终发现果真有一处数组越界,代码简单描述如下

char m_cXXLastUpdateTime[13]; char cLastUpdateTime[32]; memcpy(m_cXXLastUpdateTime, cLastUpdateTime, sizeof(cLastUpdateTime));

     m_cXXLastUpdateTime是成员变量,它的大小只有13个字节,但是在调用memcpy赋值时,却拷贝了sizeof(cLastUpdateTime)=32个字节的大小,那么就会将m_cXXLastUpdateTime地址后面的19位全部覆盖,当在程序的其他地方使用到这个地址的变量时,就会出现Access violation,问题解决了。解决这个问题的过程是比较痛苦的,因为碰上这种程序中其他地方内存越界引起的内存破坏问题,通过分析dump文件并不能准确定位到具体原因,只能一行一行地分析代码,所以我们平常写代码对数组的赋值要格外小心。

     下面以一个简单地例子来复现上述场景,例子代码如下:

#include class CheckDbf { public: CheckDbf() { memset(szTime, 0, sizeof(szTime)); memset(szText, 0, sizeof(szText)); } ~CheckDbf() { } public: char szTime[13]; char szText[5]; }; int main() { char szBuf[32] = { 0 }; sprintf(szBuf, "20190613"); CheckDbf dbf; sprintf(dbf.szText, "1234"); int nSize = sizeof(dbf); memcpy(dbf.szTime, szBuf, sizeof(szBuf)); return 0; }

     调试该代码,查看dbf对象的成员变量内存: 在这里插入图片描述     可以看到sizeof(dbf)=18,前面的13个字节为空是szTime的内容,后面的5个字节是szText的内容,ACSII码刚好是31 32 33 34 00,放开断点,走完memcpy函数,再看内存: 在这里插入图片描述      dbf对象的前面的13个字节和是szTime,并且是我们赋值的内容“20190613”,但是接下来的5个字节却全变了,因为被覆盖了,此时如果我们再访问szText并调用一些string函数,则会导致程序崩溃。将szText换成std::map成员变量也是一样的效果。 谨记: 1,memcpy时,拷贝的大小不要越界。 2,strcpy不要使用,改用strncpy,同样,拷贝的大小一定不要越界。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3