從彙編的眼光看C (之指標拷貝)

2021-12-29 16:33:22 字數 3234 閱讀 1883

指標是程式設計人員的夢魘,對c語言的開發者是如此,對c++的開發者也是如此。特別是在c++中,如果不注意處理類中的指標,非常容易出問題。如果朋友們不相信可以看看下面的**:

class data 

int* value; 

public: 

data(int num)    上面的這段問題有沒有什麼問題?大家可以自己先用筆在草稿紙上面畫一畫。然後上機用實際環境驗證一下。果不其然,系統提示記憶體發生了錯誤。為什麼呢?就是因為記憶體發生了兩次釋放。我們看以看一下process的彙編**:

21:       data m(10); 

0040105d   push        0ah 

0040105f   lea         ecx,[ebp-10h] 

00401062   call        @ilt+15(data::data) (00401014) 

00401067   mov         dword ptr [ebp-4],0 

22:       data p = m; 

0040106e   mov         eax,dword ptr [ebp-10h] 

00401071   mov         dword ptr [ebp-14h],eax 

23:   } 

00401074   lea         ecx,[ebp-14h] 

00401077   call        @ilt+5(data::~data) (0040100a) 

0040107c   mov         dword ptr [ebp-4],0ffffffffh 

00401083   lea         ecx,[ebp-10h] 

00401086   call        @ilt+5(data::~data) (0040100a) 

0040108b   mov         ecx,dword ptr [ebp-0ch] 

0040108e   mov         dword ptr fs:[0],ecx 

00401095   pop         edi 

00401096   pop         esi 

00401097   pop         ebx 

00401098   add         esp,54h 

0040109b   cmp         ebp,esp 

0040109d   call        __chkesp (004015b0) 

004010a2   mov         esp,ebp 

004010a4   pop         ebp 

004010a5   ret 

21:       data m(10);

0040105d   push        0ah

0040105f   lea         ecx,[ebp-10h]

00401062   call        @ilt+15(data::data) (00401014)

00401067   mov         dword ptr [ebp-4],0

22:       data p = m;

0040106e   mov         eax,dword ptr [ebp-10h]

00401071   mov         dword ptr [ebp-14h],eax

23:   }

00401074   lea         ecx,[ebp-14h]

00401077   call        @ilt+5(data::~data) (0040100a)

0040107c   mov         dword ptr [ebp-4],0ffffffffh

00401083   lea         ecx,[ebp-10h]

00401086   call        @ilt+5(data::~data) (0040100a)

0040108b   mov         ecx,dword ptr [ebp-0ch]

0040108e   mov         dword ptr fs:[0],ecx

00401095   pop         edi

00401096   pop         esi

00401097   pop         ebx

00401098   add         esp,54h

0040109b   cmp         ebp,esp

0040109d   call        __chkesp (004015b0)

004010a2   mov         esp,ebp

004010a4   pop         ebp

004010a5   ret

21行:data呼叫建構函式,分配記憶體給value

22行: 這裡我們發現程式進行記憶體拷貝,那麼表示m變數value的數值和p變數中value的數值是一樣的

23行:這裡函式即將結束,所以系統呼叫m和p的析構函式,第一次析構的時候value指向的記憶體被釋放,第二次析構的時候由於p變數value的數值非0,所以也需要釋放記憶體,當然也需要進行析構處理,但是此時記憶體已經釋放了,所以記憶體進行了二次釋放,系統報錯。

經過上面的研究,我們發現了問題和原因,那麼應該怎麼解決呢?既然問題是在拷貝函式這裡,那麼就要對拷貝函式進行特殊處理。目前就我個人理解,有兩個方法供大家選擇:

(1)對拷貝建構函式進行private處理,這樣一旦出現了拷貝操作,編譯器就會提示出錯。

class data 

int* value; 

data(const data&) ; 

public: 

data(int num);    (2)編寫拷貝建構函式,進行記憶體深複製

class data 

int* value; 

int number; 

public: 

data(int num) 

int get_number() const  

class data

int* value;

int number;

public:

data(int num)

int get_number() const

};    我們看到,經過拷貝建構函式的定義後,原來的process函式解可以正常編譯通過,沒有問題

用彙編的眼光看C (之指標1)

指標是我們在c c 中經常遇到的一種資料型別。指標用的好,可以提高 的可讀性 但是如果使用不恰當,反而會造成很大的麻煩。指標,也就是指向某一種資料型別的位址。這種型別很多,它可以是程式語言自帶的型別,比如說int long short char float double int 也可是是指向某一種自...

用彙編的眼光看C (之指標1)

指標是我們在c c 中經常遇到的一種資料型別。指標用的好,可以提高 的可讀性 但是如果使用不恰當,反而會造成很大的麻煩。指標,也就是指向某一種資料型別的位址。這種型別很多,它可以是程式語言自帶的型別,比如說int long short char float double int 也可是是指向某一種自...

用彙編的眼光看C (之指標1)

指標是我們在c c 中經常遇到的一種資料型別。指標用的好,可以提高 的可讀性 但是如果使用不恰當,反而會造成很大的麻煩。指標,也就是指向某一種資料型別的位址。這種型別很多,它可以是程式語言自帶的型別,比如說int long short char float double int 也可是是指向某一種自...