一个关于函数内部指针参数返回的错误调试及分析

一个关于函数内部指针参数返回的错误调试及分析

 

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万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章