C++ 中 ZeroMemory、memset
使用C/C++编程时,常使用ZeroMemory、memset或 “={0}”来对结构体对象进行初始化或清零。然而这三种方式都有各自的特点,使用时需谨慎,否则容易出现严重错误,本人今日解决一个导致宕机的bug,查了几小时,才发现是由同事乱用ZeroMemory所致。于是搜集资料,撰此文以共勉。
memset
void *memset(void *s,int ch,size_t n);是由C Run-time Library提供的提供的函数,作用是在一段内存块中填充某个给定的值,它是对较大的结构体或数组进行清零操作的一种最快方法。由于是语言层面提供,所以可跨平台使用。
示例:
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
由此可见:
- ZeroMemory实际是用memset实现的。
- ZeroMemory只能用于windows平台。
注意:
ZeroMemory和memset且于清零时,会将结构中所有字节置0,如果结构体中有虚函数或结构体成员中有虚函数,则会将虚函数指针置0,如果后续程序调用虚函数,空指针很可能导致程序崩溃!
因此,有虚函数或成员中有虚函数的结构体初始化,一定要用构造函数来完成。另外,如果一个类的结构中包含STL模板(Vector、List、Map等等),那么使用ZeroMemory对这个类的对象中进行清零操作也会引起一系列的崩溃问题(指针指向内存错误、迭代器越界访问等)。所以,再次强烈建议:类(class)只使用构造函数进行初始化,不要调用ZeroMemory进行清零操作。
示例:
#include <iostream>
#include <Windows.h>class Car
{public:virtual void Run() {}void print() { puts("hello world"); }
private:int m_speed;
};
struct SRace
{Car car;int dirver;
};int main(void)
{char str[] = "almost every programmer should know memset!";memset(str, '-', 6);puts(str);SRace race;race.car.print();memset(&race, 0, sizeof(SRace));// ZeroMemory(&race, sizeof(race));race.car.print();// 没通过虚表指针调用,没事race.car.Run();Car* pCar = &race.car;// __vfptr = 0x00000000,崩溃pCar->Run();return 0;
}
类的多个对象共享类的函数,类中函数所占空间加载时将其放到了代码区,每个类的对象都会分配其非静态成员变量空间,我们可以根据对象中成员变量的不同取值确定对象的不同状态,sizeof(class_object)就是返回对象所占空间的大小。
细化一下:
代码区存储程序的代码
数据区存放全局变量和静态变量,与常量 其实可以细化为全局/静态数据区与常量数据区
栈中存放局部变量与传来的参数
堆是动态分配使用的。
类在内存里的数据连续存储,基本上就是存几个非静态成员变量与虚函数表指针(如果存在)
={0}
={0}操作是结构体和数组的一种初始化方式,它是将结构体中基本类型变量赋默认值,当结构体中有非基本类型(例如类对象)时,会编译错误,这也是一种保护。
C++ 中 ZeroMemory、memset相关推荐
- ZeroMemory memset 等清零的用法(笔记)
ZeroMemory memset 等清零的用法(笔记) (1)函数的原型和参数的介绍 ZeroMemory函数 void ZeroMemory( PVOID Destination,SIZE_T L ...
- ZeroMemory memset 等清零的用法
ZeroMemory memset 等清零的用法(笔记) (1)函数的原型和参数的介绍 ZeroMemory函数 void ZeroMemory( PVOID Destination,SIZE_T ...
- C++对象模型4——多重继承的对象内存模型、vptr与vtbl的创建与重置的时机、不要在含有虚函数的类的构造函数中调用memset
一.多重继承的对象内存模型 class Base1 { public:virtual void f() {cout << "base1::f()" << e ...
- c语言中memset_C中的memset()
c语言中memset The memset() function in C is used to set blocks of memory with a particular value. C语言中的 ...
- C++ 中 ZeroMemory、memset 危险需慎用
使用C/C++编程时,常使用ZeroMemory.memset或 "={0}"来对结构体对象进行初始化或清零.然而这三种方式都有各自的特点,使用时需谨慎,否则容易出现严重错误,本人 ...
- 转: C++ 中 ZeroMemory、memset 易内存出错
转自:https://blog.csdn.net/tjunxin/article/details/8540259 https://blog.csdn.net/my_business/article/d ...
- Zeromemory memset
1. void ZeroMemory( PVOID Destination, SIZE_T Length); Destination :指向一块准备用0来填充的内存区域的开始地址. Length :准 ...
- 构造函数中慎用memset
写了一个小程序,工作时会跑一个大循环,在运行时发现有严重的内存泄露,内存不停增长. 经过几次复查,终于找出问题所在,代码结构大概如下: struct myobj { myobj() { memset( ...
- C++中的memset函数
memsetmemset是计算机中C/C++语言初始化函数.作用是将某一块内存中的内容全部设置为指定的值,在数组初始化上非常简便,其通式如下: memset(数组名,数组中每一个元素要定义的初始值,s ...
最新文章
- MySQL-一条sql语句的执行顺序
- [剑指offer]面试题13:在O(1)时间删除链表结点
- HTTP get post put delte等
- mysql 求bit 某位为1_mysql按位的索引判断值是否为1
- 工作309:selectaccount方法接收值
- mysql修改文件名_SQL语句实现附加数据库,可以改数据库物理文件名
- plesk 打不开php,如何在 Plesk 中管理 PHP
- Visual Basic6.0下载及安装
- 自动驾驶路径规划——A*(Astar)算法
- win7 变wifi热点
- java deflate,java.util.zip.Deflater.deflate(byte[] b, int off, int len)方法示例
- oracle图书操作、sql语句查询+授权、视图、索引、表操作
- 再谈计算机编程的学习
- 搭建Openstack环境以及Openstack认证服务
- linux hosts文件的修改------利用root权限来vim /etc/hosts
- CSP202109-4 收集卡牌
- gem 安装oxidized-web报错:checking for -licui18n... no处理
- 在种子轮中,如何区分风险投资、种子投资和天使投资?
- Numpy:关于flatten的理解
- 使用计算机配置路由器,用命令配置路由器基础(
热门文章
- Java的System.getProperty()方法获取信息的用法
- Oracle故障案例 | 19C动态监听无法注册实例的处理
- Springboot整合activiti(最详细版)
- ai图片怎么把图中的字改掉_ai cs6 隐藏透视网格和ai怎么把图片中的文字抠出来...
- 弘辽科技:拼多多商家如何自己提升销量?提升销量需要注意什么?
- 产业分析:2022广东省产业全景
- python(moviepy ) mp4视频拼接截取
- Memcached 与Redis缓存服务器介绍
- 监听剪切板内容,解决复制粘贴内容格式错乱
- java eden s0 s1_不是吧!做了两年java还没弄懂JVM堆?进来看看你就明白了