老生常谈,正确使用memset
生活随笔
收集整理的這篇文章主要介紹了
老生常谈,正确使用memset
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
前段項(xiàng)目中發(fā)現(xiàn)一個(gè)問(wèn)題,程序總是在某個(gè)dynamic_cast進(jìn)行動(dòng)態(tài)轉(zhuǎn)換時(shí)出異常,查了半天才發(fā)現(xiàn)問(wèn)題原來(lái)是出在memset的使用上,雖然問(wèn)題本身顯而易見(jiàn),但當(dāng)處于幾十萬(wàn)行代碼量級(jí)中時(shí),就變得不太那么容易定位了。
本文歸納了下使用memset幾個(gè)需要注意的地方,雖然內(nèi)容很簡(jiǎn)單,但也希望對(duì)大家有所幫助。
1. memset是以字節(jié)為單位,初始化內(nèi)存塊。 當(dāng)初始化一個(gè)字節(jié)單位的數(shù)組時(shí),可以用memset把每個(gè)數(shù)組單元初始化成任何你想要的值,比如, [cpp] view plaincopy print?char?data[10];?? memset(data,?1,?sizeof(data));????//?right?? memset(data,?0,?sizeof(data));????//?right??
char data[10];
memset(data, 1, sizeof(data)); // right
memset(data, 0, sizeof(data)); // right
而在初始化其他基礎(chǔ)類型時(shí),則需要注意,比如,
[cpp] view plaincopy print? int?data[10];?? memset(data,?0,?sizeof(data));????//?right?? memset(data,?-1,?sizeof(data));????//?right?? memset(data,?1,?sizeof(data));????//?wrong,?data[x]?would?be?0x0101?instead?of?1??
int data[10];
memset(data, 0, sizeof(data)); // right
memset(data, -1, sizeof(data)); // right
memset(data, 1, sizeof(data)); // wrong, data[x] would be 0x0101 instead of 1
2. 當(dāng)結(jié)構(gòu)體類型中包含指針時(shí),在使用memset初始化時(shí)需要小心。
比如如下代碼中,
[cpp] view plaincopy print? struct?Parameters?{?? ??????????int?x;?? ??????????int*?p_x;?? };?? Parameters?par;?? par.p_x?=?new?int[10];?? memset(&par,?0,?sizeof(par));?? struct Parameters {int x;int* p_x;
};
Parameters par;
par.p_x = new int[10];
memset(&par, 0, sizeof(par));
當(dāng)memset初始化時(shí),并不會(huì)初始化p_x指向的int數(shù)組單元的值,而會(huì)把已經(jīng)分配過(guò)內(nèi)存的p_x指針本身設(shè)置為0,造成內(nèi)存泄漏。同理,對(duì)std::vector等數(shù)據(jù)類型,顯而易見(jiàn)也是不應(yīng)該使用memset來(lái)初始化的。
3. 當(dāng)結(jié)構(gòu)體或類的本身或其基類中存在虛函數(shù)時(shí),也需要謹(jǐn)慎使用memset。 這個(gè)問(wèn)題就是在開(kāi)頭項(xiàng)目中發(fā)現(xiàn)的問(wèn)題,如下代碼中, [cpp] view plaincopy print?class?BaseParameters?? {?? public:?? ????virtual?void?reset()?{}?? };?? ?? class?MyParameters?:?public?BaseParameters?? {?? public:??? ????int?data[3];?? ????int?buf[3];?? };?? ?? MyParameters?my_pars;?? memset(&my_pars,?0,?sizeof(my_pars));?? BaseParameters*?pars?=?&my_pars;?? ?? //......?? ?? MyParameters*?my?=?dynamic_cast<MyParameters*>(pars);?? class BaseParameters
{
public:virtual void reset() {}
};class MyParameters : public BaseParameters
{
public: int data[3];int buf[3];
};MyParameters my_pars;
memset(&my_pars, 0, sizeof(my_pars));
BaseParameters* pars = &my_pars;//......MyParameters* my = dynamic_cast<MyParameters*>(pars);
程序運(yùn)行到dynamic_cast時(shí)發(fā)生異常。原因其實(shí)也很容易發(fā)現(xiàn),我們的目的是為了初始化數(shù)據(jù)結(jié)構(gòu)MyParameters里的data和buf,正常來(lái)說(shuō)需要初始化的內(nèi)存空間是sizeof(int) * 3 * 2 = 24字節(jié),但是使用memset直接初始化MyParameters類型的數(shù)據(jù)結(jié)構(gòu)時(shí),sizeof(my_pars)卻是28字節(jié),因?yàn)闉榱藢?shí)現(xiàn)多態(tài)機(jī)制,C++對(duì)有虛函數(shù)的對(duì)象會(huì)包含一個(gè)指向虛函數(shù)表(V-Table)的指針,當(dāng)使用memset時(shí),會(huì)把該虛函數(shù)表的指針也初始化為0,而dynamic_cast也使用RTTI技術(shù),運(yùn)行時(shí)會(huì)使用到V-Table,可此時(shí)由于與V-Table的鏈接已經(jīng)被破壞,導(dǎo)致程序發(fā)生異常。
1. memset是以字節(jié)為單位,初始化內(nèi)存塊。 當(dāng)初始化一個(gè)字節(jié)單位的數(shù)組時(shí),可以用memset把每個(gè)數(shù)組單元初始化成任何你想要的值,比如, [cpp] view plaincopy print?
3. 當(dāng)結(jié)構(gòu)體或類的本身或其基類中存在虛函數(shù)時(shí),也需要謹(jǐn)慎使用memset。 這個(gè)問(wèn)題就是在開(kāi)頭項(xiàng)目中發(fā)現(xiàn)的問(wèn)題,如下代碼中, [cpp] view plaincopy print?
總結(jié)
以上是生活随笔為你收集整理的老生常谈,正确使用memset的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: matlab多元函数_函数的计算机处理8
- 下一篇: c的关于数组初始化 和 memset用法