zoukankan      html  css  js  c++  java
  • 纪念在“返回局部变量的指针”导致的错误上耗费的一天

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

    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] = '';
    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] = '';
    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值也会被改变。

  • 相关阅读:
    五、敏捷开发框架 初识组件式开发
    winform 控制Text Box只能输入英文数字和退格键
    WPF 常用控件属性
    问题分析
    串口通讯学习
    解决MVC中Model上的特性在EF框架刷新时清空的问题
    论序列化与反序列化
    dynamics 365 安全角色及权限
    .NET Core 依赖注入框架 框图笔记
    C#基本类型的取值范围与 .NET框架类型的对应
  • 原文地址:https://www.cnblogs.com/zhouliyan/p/5468096.html
Copyright © 2011-2022 走看看