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


    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 <string>
    
    
    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,同样,拷贝的大小一定不要越界。

    from:https://blog.csdn.net/bajianxiaofendui/article/details/91896431

  • 相关阅读:
    离线安装 Framework 3.5 镜像安装
    换行符处理
    使用 JSON JavaScriptSerializer 进行序列化或反序列化时出错。字符串的长度超过了为 maxJsonLength 属性设置的值。
    vs 无法启动iis express web服务器
    OracleInternal.MTS.DTCPSPEManager”的类型初始值设定项引发异常
    纯前端上传文件FormData----注意的地方
    LINQ 的一些相关基本语法
    Spread JS 随笔四 相关用法
    Spread JS 随笔三 列设置
    findbugs报OBL_UNSATISFIED_OBLIGATION_EXCEPTION_EDGE的修改实例
  • 原文地址:https://www.cnblogs.com/lidabo/p/14381389.html
Copyright © 2020-2023  润新知