使用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/
示例:

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

输出:

------ every programmer should know memset!

ZeroMemory

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

#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进行清零操作。

示例:

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

C++ 中 ZeroMemory、memset 危险需慎用相关推荐

  1. C++基础之:memset 、ZeroMemory和 “={0}” 三者区别及危险需慎用

    memset是以字节为单位,初始化内存块. 当初始化一个字节单位的数组时,可以用memset把每个数组单元初始化成任何你想要的值, 比如 char data[10]; memset(data, 1, ...

  2. ZeroMemory memset 等清零的用法(笔记)

    ZeroMemory memset 等清零的用法(笔记) (1)函数的原型和参数的介绍 ZeroMemory函数 void ZeroMemory( PVOID Destination,SIZE_T L ...

  3. ZeroMemory memset 等清零的用法

     ZeroMemory memset 等清零的用法(笔记) (1)函数的原型和参数的介绍 ZeroMemory函数 void ZeroMemory( PVOID Destination,SIZE_T ...

  4. java 绑定微信号开发_Java开发中的常见危险信号

    java 绑定微信号开发 在开发,阅读,复审和维护成千上万行Java代码的几年中,我已经习惯于看到Java代码中的某些" 危险信号 ",这些信号通常(但可能并非总是)暗示着代码有问 ...

  5. C++对象模型4——多重继承的对象内存模型、vptr与vtbl的创建与重置的时机、不要在含有虚函数的类的构造函数中调用memset

    一.多重继承的对象内存模型 class Base1 { public:virtual void f() {cout << "base1::f()" << e ...

  6. python模拟通讯录的删除功能_python+uiautomator2 实现需求:从通讯录添加手机号码,若存在旧的 SOS号码,先删除再添加,若通讯录中没有号码,需先新建。...

    # 实现需求:从通讯录添加手机号码,若存在旧的SOS号码,先删除再添加,若通讯录中没有号码,需先新建. import uiautomator2 as u2 from time import sleep ...

  7. java memcached 存储对象_memcached—向memcached中保存Java实体需注意的问题

    今天以代码实例的形式总结一下向memcached中保存Java实体需注意的问题: memcached工具类代码: package com.ghj.packageoftool; import java. ...

  8. Java开发中的常见危险信号

    在开发,阅读,复审和维护成千上万行Java代码的几年中,我已经习惯于看到Java代码中的某些" 危险信号 ",这些信号通常(但可能并非总是)暗示着代码问题. 我不是在谈论总是错误的 ...

  9. java中main方法返回类型是6_[单选] Java application中的主类需包含main方法,main方法的返回类型是什么()。...

    [单选] Java application中的主类需包含main方法,main方法的返回类型是什么(). 更多相关问题 关于超声在人体中传播的速度,叙述正确的有A.与人体组织的弹性有关B.与人体组织的 ...

最新文章

  1. KVM — Overview
  2. 解决jquey中当事件嵌套时,内层事件会执行多次的问题
  3. 虚拟机安装Ubuntu过程记录
  4. eclipse配置java环境_Java工作环境的配置与Eclipse的安装过程
  5. java 读取ppt文件_java使用poi读取ppt文件和poi读取excel、word示例
  6. 计算机里什么文件无法删除,电脑上的文件删不掉怎么办
  7. 使用值类型LazyString分析字符串
  8. v8的垃圾回收机制(二)
  9. 操作系统复习笔记(二)
  10. 孪生神经网络_驾驶习惯也能识人?基于时空孪生神经网络的轨迹识别
  11. Objective-C 基础,类和对象,方法和消息,已声明的属性和存取方法,块对象,协议和范畴类,预定义类型和编码策略...
  12. bilibili视频下载到电脑本地教程
  13. 甩开炎热去15℃的四川秘境度假,这里有藏于田园风景的纯白民宿
  14. 抖音巨量千川是什么?和飞瓜智投有什么不同?后者功能更强大!
  15. vue-cli、脚手架创建、eslint、alias别名配置、proxy代理配置、axios、scoped、穿透、媒体查询、12栅格、动态rem、1px边框、移动端事件、300ms延迟问题(六)
  16. 腾讯实时音视频通话sdk集成----小程序版本
  17. python批量删除文件前缀名_Python3-去除目录中相同的文件名前缀
  18. ArcGIS教程:曲率
  19. 一劳永逸,使用 PicGo + GitHub 搭建个人图床工具
  20. 学习记录01:使用pyqt5搭建yolo3目标识别界面

热门文章

  1. 游戏外挂原理和技术分析(关于魔力宝贝)
  2. pyaudio usb playback_苹果还会为 iPhone 换上 USB-C 吗?_详细解读_最新资讯_热点事件...
  3. 黄凯:将信息安全当成企业的生产要素
  4. linux下如何实现文件共享
  5. 【Prompting】ChatGPT Prompt Engineering开发指南(1)
  6. 软件需求变更管理七步法
  7. Adobe Substance 3D Designer 问题集
  8. 视频编解码绿边的问题
  9. react 嵌套iframe_React中使用iframe嵌套百度拾取坐标系统
  10. Python语言程序设计基础(第二版)P93答案示例