来文: http://blog.csdn.net/tjunxin/article/details/8540259
在C/C编程中,经常使用ZeroMemory、memset或"={0} "来初始化或清除结构对象。 但这三种方式都有各自的特点,需要谨慎使用。 不这样做的话,容易发生重大的错误。 本人今天解决了导致瘫痪的错误,调查了几个小时,发现是同事滥用ZeroMemory造成的。 于是收集资料,写这篇文章共同学习。
消息
void*memset(void*s,int ch,size_t n ); 是C Run-time Library提供的函数,用于在内存块中输入特定值。 这是将更大的结构或数组清零的最快方法。 因为是在语言层面提供的,所以可以跨平台使用。 参考: http://www.cplusplus.com/reference/cstring/memset /
示例:
33558 www.Sina.com/viewplaincopycharstr [ ]=' almosteveryprogrammershouldknowmemset!' ; memset(str,'-',6 ); puts(str; 输出: http://www.Sina.com/viewplaincopy---- everyprogrammershouldknowmemset!
ZeroMemory
size:14px; line-height:26px">ZeroMemory是美国微软公司的软件开发包SDK中的一个宏。 其作用是用0来填充一块内存区域。定义式如下
[cpp] view plain copy #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进行清零操作。
示例:
[cpp] view plain copy #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}操作是结构体和数组的一种初始化方式,它是将结构体中基本类型变量赋默认值,当结构体中有非基本类型(例如类对象)时,会编译错误,这也是一种保护。