一個關於函數內部指針參數返回的錯誤調試及分析

一個關於函數內部指針參數返回的錯誤調試及分析

 

C語言中如下兩個概念是非常重要,但又是極其容易在編程中出問題的:

1.       C語言中指針存儲的是一個地址,而非實際的數據項內容。

2.       C語言中函數內部定義的變量的作用域或生存空間只在函數內。

下面就本人在編程中出現的一個錯誤代碼進行分析,(這個代碼出的問題就是以上2點。)除此之外提出一個gcc導致該程序費了很大功夫才找到這2個錯誤的bug

01#include<stdio.h>

02#include<stdlib.h>

03struct test{

04int x;

05int y;      

06};

07struct test2{

08int z;

09struct test *w;

10};

11void fun(struct test2 *st)

12{

13struct test fst;

14fst.x=1;

15fst.y=2;

16st->w=&fst;

17printf("fun:   %d %d /n",fst.x,fst.y);

18}

19

20void print(struct test2 *st)

21{

22printf("print:%d %d/n",st->w->x,st->w->y);

23}

24

25int main()

26{

27struct test2 *mst;

28mst=(struct test2 *)calloc(1,sizeof(struct test2));

29mst->w=(struct test *)calloc(1,sizeof(struct test));

30fun(mst);

31printf("main:  %d %d/n",mst->w->x,mst->w->y);

32print(mst);

33return 0;

34}

該代碼的錯誤在於,16行處,將fun函數內的局部變量fst的地址交給了指針參數st->w,從而主函數中打印輸出的時候st->w指針所指的內容由於fun函數的返回而被系統回收了。

現在看來原理非常簡單。但調試該段代碼卻花費了本人很多時間。執行上面的程序我們得到如下的結果:

01fun:   1 2

02main:  1 2

03print:2013480168 -1

 

在結果第1行返回正確的值1 2,並且在第2行,仍然返回的是1 2。這就讓人搞不清楚了,由現在的輸出怎麼也不會讓人聯想到在fun函數裏面就出了問題,因爲在31main函數中輸出了正確的結果1 2,從而檢查的焦點不自覺的就轉移到32行調用的print函數。但該函數本來就沒有任何錯誤,自然就陷入了麻煩之中了。

       我們再看下面這個程序:

01#include<stdio.h>

02#include<stdlib.h>

03struct test

04{

05int x;

06int y;      

07};

08

09void fun(struct test *st)

10{

11struct test fst;

12fst.x=1;

13fst.y=2;

14st=&fst;

15printf("fun:%d %d/n",fst.x,fst.y);

16}

17int main()

18{

19struct test *mst;

20mst=(struct test *)calloc(1,sizeof(struct test));

21fun(mst);

22printf("main:%d %d /n",mst->x,mst->y);

23return 0;

24}

同樣的再14fun函數中錯誤的將局部變量fst的地址給了參數指針,而主函數中該地址被系統回收,得到如下的結果:

01fun:1 2

02main:0 0

這個就比較明顯的看出效果來,在fun函數返回後,main函數中輸出的結果已經被清零了,說明fun函數部分有問題。

我們再回過頭看看第一個代碼,爲什麼會出現前面的狀況,2個代碼不同之處在於,第一個代碼中結構體的成員本身也是指針,我們是對這個成員指針進行的操作,在fun返回後系統並沒有對該成員引用的地址進行銷燬(應該算是gcc的一個bug),所以在31行的main函數中返回的仍然是1 2,而32行調用print函數時,系統將保存當前的斷點地址等信息,該信息恰好寫入了原來fun函數分配的局部變量fst的地址,從而改變了原有的數據內容1 2,所以輸出結果的第3行,得到了一個錯誤的結果。

 

發佈了20 篇原創文章 · 獲贊 12 · 訪問量 16萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章