zoukankan      html  css  js  c++  java
  • C++ 中 ZeroMemory、memset 危险需慎用 (转)

    使用C/C++编程时,常使用ZeroMemory、memset或 “={0}”来对结构体对象进行初始化或清零。然而这三种方式都有各自的特点,使用时需谨慎,否则容易出现严重错误,导致宕机的bug,乱用ZeroMemory所致。 

    http://www.cplusplus.com/reference/cstring/memset/
    示例:

    1. char str[] = "almost every programmer should know memset!";  
    2. memset (str,'-',6);  
    3. puts (str);  
    char str[] = "almost every programmer should know memset!";
    memset (str,'-',6);
    puts (str);


    输出:

    1. ------ every programmer should know memset!  
    ------ every programmer should know memset!

    ZeroMemory

    ZeroMemory是美国微软公司的软件开发包SDK中的一个宏。 其作用是用0来填充一块内存区域。定义式如下

    1. #define RtlZeroMemory(Destination,Length) memset((Destination),0,(Length))   
    2. #define ZeroMemory RtlZeroMemory  
    #define RtlZeroMemory(Destination,Length) memset((Destination),0,(Length))
    #define ZeroMemory RtlZeroMemory

     

    由此可见:

    1. ZeroMemory实际是用memset实现的。
    2.  ZeroMemory只能用于windows平台。

    注意:

    ZeroMemory和memset且于清零时,会将结构中所有字节置0,如果结构体中有虚函数或结构体成员中有虚函数,则会将虚函数指针置0,如果后续程序调用虚函数,空指针很可能导致程序崩溃!

    因此,有虚函数或成员中有虚函数的结构体初始化,一定要用构造函数来完成。

    另外,如果一个类的结构中包含STL模板(Vector、List、Map等等),那么使用ZeroMemory对这个类的对象中进行清零操作也会引起一系列的崩溃问题(指针指向内存错误、迭代器越界访问等)。所以,再次强烈建议:类(class)只使用构造函数进行初始化,不要调用ZeroMemory进行清零操作。

    示例:

    1. #include "stdafx.h"   
    2. #include <Windows.h>   
    3.   
    4. class Car  
    5. {  
    6. public:  
    7.     virtual void Run(){}  
    8. private:  
    9.     int m_speed;  
    10. };  
    11. struct  SRace    
    12. {  
    13.     Car car;  
    14.     int dirver;  
    15. };  
    16.   
    17. int _tmain(int argc, _TCHAR* argv[])  
    18. {  
    19.     SRace race;  
    20.     ZeroMemory(&race,sizeof(race));  
    21.       
    22.     // 没通过虚表指针调用,没事   
    23.     race.car.Run();  
    24.       
    25.     Car *pCar = &race.car;  
    26.   
    27.     // __vfptr = 0x00000000,崩溃   
    28.     pCar->Run();  
    29.   
    30.     return 0;  
    31. }  
    #include "stdafx.h"
    #include <Windows.h>
    
    class Car
    {
    public:
    	virtual void Run(){}
    private:
    	int m_speed;
    };
    struct	SRace  
    {
    	Car car;
    	int dirver;
    };
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	SRace race;
    	ZeroMemory(&race,sizeof(race));
    	
    	// 没通过虚表指针调用,没事
    	race.car.Run();
    	
    	Car *pCar = &race.car;
    
    	// __vfptr = 0x00000000,崩溃
    	pCar->Run();
    
    	return 0;
    }

     

    ={0}

    ={0}操作是结构体和数组的一种初始化方式,它是将结构体中基本类型变量赋默认值,当结构体中有非基本类型(例如类对象)时,会编译错误,这也是一种保护。

  • 相关阅读:
    Android开发 ViewConfiguration View的配置信息类
    Android 开发 倒计时功能 转载
    Android 开发 关于7.0 FileUriExposedException异常 详解
    Android 开发 实现文本搜索功能
    Android 开发 Activity里获取View的宽度和高度 转载
    Android 开发 存储目录的详解
    Android 开发 Fresco框架点击小图显示全屏大图实现 ZoomableDraweeView
    Android 开发 将window变暗
    Android 开发 DisplayMetrics获取Android设备的屏幕高宽与其他信息
    Android 开发 DP、PX、SP转换详解
  • 原文地址:https://www.cnblogs.com/For-her/p/3897490.html
Copyright © 2011-2022 走看看