memset用法

       memset是計算機中C/C++語言函數。將s所指向的某一塊內存中的前n個 字節的內容全部設置爲ch指定的ASCII值, 第一個值爲指定的內存地址,塊的大小由第三個參數指定,這個函數通常爲新申請的內存做初始化工作, 其返回值爲指向s的指針


其原型爲:void *memset(void *s, int ch, size_t n);
函數解釋:將s中當前位置後面的n個字節 (typedef unsigned int size_t )用 ch 替換並返回 s 。


       1. memset是以字節爲單位,初始化內存塊。
當初始化一個字節單位的數組時,可以用memset把每個數組單元初始化成任何你想要的值,比如:

char data[10];  
memset(data, 1, sizeof(data));    // right  
memset(data, 0, sizeof(data));    // right  

而在初始化其他基礎類型時,則需要注意,比如:


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. 當結構體類型中包含指針時,在使用memset初始化時需要小心。
比如如下代碼中,
struct Parameters {  
          int x;  
          int* p_x;  
};  
Parameters par;  
par.p_x = new int[10];  
memset(&par, 0, sizeof(par));  

當memset初始化時,並不會初始化p_x指向的int數組單元的值,而會把已經分配過內存的p_x指針本身設置爲0,造成內存泄漏。同理,對std::vector等數據類型,顯而易見也是不應該使用memset來初始化的。

3. 當結構體或類的本身或其基類中存在虛函數時,也需要謹慎使用memset。
這個問題就是在開頭項目中發現的問題,如下代碼中:

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);  

程序運行到dynamic_cast時發生異常。原因其實也很容易發現,我們的目的是爲了初始化數據結構MyParameters裏的data和buf,正常來說需要初始化的內存空間是sizeof(int) * 3 * 2 = 24字節,但是使用memset直接初始化MyParameters類型的數據結構時,sizeof(my_pars)卻是28字節,因爲爲了實現多態機制,C++對有虛函數的對象會包含一個指向虛函數表(V-Table)的指針,當使用memset時,會把該虛函數表的指針也初始化爲0,而dynamic_cast也使用RTTI技術,運行時會使用到V-Table,可此時由於與V-Table的鏈接已經被破壞,導致程序發生異常。




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章