纪念在“返回局部变量的指针”导致的错误上耗费的一天

最近在写编译器,有这样一段代码

1 typedef struct{
2     int symbolnum;
3     char *name;     //id36
4     int i;          //int37
5     float f;        //float38
6     char *s;        //string39
7 }To;
8 typedef To* Token;
 1 Token ReadToken()        //从fp文件中读取一行形如(36,sum)的行,返回值被压栈
 2 {
 3     char strLine[1024];
 4     char n1[10];
 5     char n2[20];
 6     int i=0,j=0;
 7     int t1;
 8     Token rt = (Token)malloc(sizeof(To));
 9     if(feof(fp)||(NULL == fgets(strLine,1024,fp)))
10     {
11         rt->symbolnum = 0;
12         return rt;
13     }
14 
15     for(i=1;;i++)
16     {
17         if(strLine[i] == ',')
18         {
19             n1[i-1] = '\0';
20             t1 = atoi(n1);
21             break;
22         }
23         n1[i-1] = strLine[i];
24     }
25     rt->symbolnum = yytranslate[t1];
26     i++;
27 
28     while(strLine[i] != ')')
29     {
30         n2[j] = strLine[i];
31         j++;
32         i++;
33     }
34     n2[j] = '\0';
35             
36     switch(t1)
37     {
38     case 36:        //id
39         {
40             rt->name = n2;        //我一定是脑子烧糊涂了才会这样写
41             break;
42         }
43     case 37:        //int
44         {
45             rt->i = atoi(n2);
46             break;
47         }
48     case 38:        //float
49         {
50             rt->f = atof(n2);
51             break;
52         }
53     case 39:        //string
54         {
55             rt->s = n2;          ///(ㄒoㄒ)/~~
56             break;
57         }
58     }
59     return rt;
60 }

 这段代码错在什么地方呢?

结构体To中的name和s的类型都是char*,即指针型的字符串。在函数ReadToken()中

40             rt->name = n2;

直接将n2字符数组的地址赋值给name,n2是个局部变量,在函数退出后就会被销毁,n2地址中的值也没了,但是rt返回给主函数被压栈,rt->name还是这个地址,这个地址现在存啥呢?不一定。将来存啥呢?不一定。

在c语言中,一种典型的错误就是将一个指向局部变量的指针作为函数的返回值。由于该数组是局部变量,因此在函数返回时其数组空间已经作废了,即指针应用一块无意义的地址空间,所以不会有返回值。

如果得到正常的值,只能是幸运的:退出函数的时候,系统只是修改了栈顶的指针,并没有清内存; 所以,是有可能正常访问到局部变量的内存的。 
但因为栈是系统自动管理的,所以该内存可能会被分配给其他函数,这样,该内存的内容就会被覆盖;不再是原来的值了。

下一次执行ReadToken()又会为n2申请空间,这个和上一次被销毁的地址应该是一样的,所以这次执行ReadToken()时,一旦对n2的值改变,栈中原来那个token的name值也会被改变。

posted @ 2016-05-07 11:59  lyzhou  阅读(517)  评论(0编辑  收藏  举报