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

    使用C/C++编程时,常使用ZeroMemory、memset或 “={0}”来对结构体对象进行初始化或清零。然而这三种方式都有各自的特点,使用时需谨慎,否则容易出现严重错误,本人今日解决一个导致宕机的bug,查了几小时,才发现是由同事乱用ZeroMemory所致。于是搜集资料,撰此文以共勉。

    memset

    void *memset(void *s,int ch,size_t n); 是由C Run-time Library提供的提供的函数,作用是在一段内存块中填充某个给定的值,它是对较大的结构体或数组进行清零操作的一种最快方法。由于是语言层面提供,所以可跨平台使用。参考:http://www.cplusplus.com/reference/cstring/memset/
    示例:

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

    输出:

    [cpp] view plain copy
    1. ------ every programmer should know memset!  

    ZeroMemory

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

    [cpp] view plain copy
    1. #define RtlZeroMemory(Destination,Length) memset((Destination),0,(Length))  
    2. #define ZeroMemory RtlZeroMemory  

    由此可见:

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

    注意:

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

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

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

    示例:

    [cpp] view plain copy
    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. }  

    ={0}

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

  • 相关阅读:
    Go 语言简介(下)— 特性
    Array.length vs Array.prototype.length
    【转】javascript Object使用Array的方法
    【转】大话程序猿眼里的高并发架构
    【转】The magic behind array length property
    【转】Build Your own Simplified AngularJS in 200 Lines of JavaScript
    【转】在 2016 年做 PHP 开发是一种什么样的体验?(一)
    【转】大话程序猿眼里的高并发
    php通过token验证表单重复提交
    windows 杀进程软件
  • 原文地址:https://www.cnblogs.com/thisway/p/5509840.html
Copyright © 2011-2022 走看看