C++ 中 ZeroMemory、memset 危險需慎用
使用C/C++編程時,常使用ZeroMemory、memset或 “={0}”來對結(jié)構(gòu)體對象進(jìn)行初始化或清零。然而這三種方式都有各自的特點,使用時需謹(jǐn)慎,否則容易出現(xiàn)嚴(yán)重錯誤,本人今日解決一個導(dǎo)致宕機(jī)的bug,查了幾小時,才發(fā)現(xiàn)是由同事亂用ZeroMemory所致。于是搜集資料,撰此文以共勉。
memset
void *memset(void *s,int ch,size_t n); 是由C Run-time Library提供的提供的函數(shù),作用是在一段內(nèi)存塊中填充某個給定的值,它是對較大的結(jié)構(gòu)體或數(shù)組進(jìn)行清零操作的一種最快方法。由于是語言層面提供,所以可跨平臺使用。參考:http://www.cplusplus.com/reference/cstring/memset/
示例:
[cpp] view plaincopyprint? char?str[]?=?"almost?every?programmer?should?know?memset!";??memset?(str,'-',6);??puts?(str);??
char?str[]?=?"almost?every?programmer?should?know?memset!"; memset?(str,'-',6); puts?(str);
輸出:
[cpp]
view plaincopyprint?
------?every?programmer?should?know?memset!??
------?every?programmer?should?know?memset!
ZeroMemory
ZeroMemory是美國微軟公司的軟件開發(fā)包SDK中的一個宏。 其作用是用0來填充一塊內(nèi)存區(qū)域。定義式如下
[cpp] view plaincopyprint? #define?RtlZeroMemory(Destination,Length)?memset((Destination),0,(Length))??#define?ZeroMemory?RtlZeroMemory??
#define?RtlZeroMemory(Destination,Length)?memset((Destination),0,(Length)) #define?ZeroMemory?RtlZeroMemory
由此可見:
ZeroMemory實際是用memset實現(xiàn)的。?ZeroMemory只能用于windows平臺。
注意:
ZeroMemory和memset且于清零時,會將結(jié)構(gòu)中所有字節(jié)置0,如果結(jié)構(gòu)體中有虛函數(shù)或結(jié)構(gòu)體成員中有虛函數(shù),則會將虛函數(shù)指針置0,如果后續(xù)程序調(diào)用虛函數(shù),空指針很可能導(dǎo)致程序崩潰!
因此,有虛函數(shù)或成員中有虛函數(shù)的結(jié)構(gòu)體初始化,一定要用構(gòu)造函數(shù)來完成。
另外,如果一個類的結(jié)構(gòu)中包含STL模板(Vector、List、Map等等),那么使用ZeroMemory對這個類的對象中進(jìn)行清零操作也會引起一系列的崩潰問題(指針指向內(nèi)存錯誤、迭代器越界訪問等)。所以,再次強(qiáng)烈建議:類(class)只使用構(gòu)造函數(shù)進(jìn)行初始化,不要調(diào)用ZeroMemory進(jìn)行清零操作。
示例:
[cpp] view plaincopyprint? #include?"stdafx.h"??#include?