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

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

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值也会被改变。

时间: 2024-10-13 06:20:58

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

c/c++不能返回局部对象和局部变量的指针或引用解释

在编写c/c++代码时,调用函数的书写让程序变得整洁易读,但是调用函数的返回值(局部变量的返回值,变量,结构体,数组等)也有注意事项.c/c++严禁返回局部变量的指针或引用. 其实函数的返回值的规则非常好记: 函数的返回值可以是数值和全局变量的指针或引用. 函数的返回值不能是局部对象或者是局部变量的指针或引用!!! 原因: 调用函数的局部变量是存在于栈中的,在执行完调用函数之后会将局部变量的空间释放,也就是调用函数执行后局部变量将不存在与内存中.如果返回的是局部变量的指针或者是引用.返回给接收对

C++编程经验-返回局部变量的讨论(转)

返回局部变量没问题 如果返回局部变量有问题,函数的意义还有吗? 全局变量还用返回吗? 返回指向局部变量的指针才有问题, 函数退栈之后,局部变量消失, 指针将指向未知区域,所以出现问题. 返回局部变量的引用也是绝对不可以的. 引用只是变量的一个别名,变量本体都不存在了,引用当然也没有任何意义. 还有,如果是堆空间,可以返回,即在函数中用new申请的空间,是可以返回的. 但是一般的情况下,好的风格是: 尽量在同一个作用域内成对使用new   和delete,(也即不要返回堆空间),因为如果不是这样,

【转】函数返回局部变量

(看到C++ Primer(P.225)“return reference to local object”时有点懵,然后找到了这篇博文.) 一般的来说,函数是可以返回局部变量的. 局部变量的作用域只在函数内部,在函数返回后,局部变量的内存已经释放了.因此,如果函数返回的是局部变量的值,不涉及地址,程序不会出错.但是如果返回的是局部变量的地址(指针)的话,程序运行后会出错.因为函数只是把指针复制后返回了,但是指针指向的内容已经被释放了,这样指针指向的内容就是不可预料的内容,调用就会出错.准确的来

函数返回局部变量

一般的来说,函数是可以返回局部变量的. 局部变量的作用域只在函数内部,在函数返回后,局部变量的内存已经释放了.因此,如果函数返回的是局部变量的值,不涉及地址,程序不会出错.但是如果返回的是局部变量的地址(指针)的话,程序运行后会出错.因为函数只是把指针复制后返回了,但是指针指向的内容已经被释放了,这样指针指向的内容就是不可预料的内容,调用就会出错.准确的来说,函数不能通过返回指向栈内存的指针(注意这里指的是栈,返回指向堆内存的指针是可以的). 下面以函数返回局部变量的指针举几个典型的例子来说明:

(十二)函数返回局部变量

一般的来说,函数是可以返回局部变量的. 局部变量的作用域只在函数内部,在函数返回后,局部变量的内存已经释放了.因此,如果函数返回的是局部变量的值,不涉及地址,程序不会出错.但是如果返回的是局部变量的地址(指针)的话,程序运行后会出错.因为函数只是把指针复制后返回了,但是指针指向的内容已经被释放了,这样指针指向的内容就是不可预料的内容,调用就会出错.准确的来说,函数不能通过返回指向栈内存的指针(注意这里指的是栈,返回指向堆内存的指针是可以的). 下面以函数返回局部变量的指针举几个典型的例子来说明:

[转]C++编程经验-返回局部变量的讨论

返回局部变量没问题 如果返回局部变量有问题,函数的意义还有吗? 全局变量还用返回吗? 返回指向局部变量的指针才有问题, 函数退栈之后,局部变量消失, 指针将指向未知区域,所以出现问题. 返回局部变量的引用也是绝对不可以的. 引用只是变量的一个别名,变量本体都不存在了,引用当然也没有任何意义. 还有,如果是堆空间,可以返回,即在函数中用new申请的空间,是可以返回的. 但是一般的情况下,好的风格是: 尽量在同一个作用域内成对使用new   和delete,(也即不要返回堆空间),因为如果不是这样,

返回局部变量

返回局部变量 一般的来说,函数是可以返回局部变量的. 局部变量的作用域只在函数内部,在函数返回后,局部变量的内存已经释放了.因此,如果函数返回的是局部变量的值,不涉及地址,程序不会出错.但是如果返回的是局部变量的地址(指针)的话,程序运行后会出错.因为函数只是把指针复制后返回了,但是指针指向的内容已经被释放了,这样指针指向的内容就是不可预料的内容,调用就会出错.准确的来说,函数不能通过返回指向栈内存的指针(注意这里指的是栈,返回指向堆内存的指针是可以的). 1. 返回局部变量的值 可以有两种情况

切勿使用:指向局部变量的指针作为函数的返回指针!

今天码代码的时候,出现了一个诡异的问题: 首先:函数 pkt_analyzer 返回了一个 PktUnit类型的指针.我先把端点跑到puu赋值后的下一句,查看puu里面的内容,发现是正确的: payload_len = 7,pkt_len = 35 接着我再向下跑一步,发现puu内容就不对了: payload_len = 1514280713 ;pkt_len = 17 整个就不对了-- 找了一个多小时,没发现问题出在哪儿!后来突然想到,可能是函数返回的时候出的问题,不能光看函数的立即返回结果!

函数返回局部变量的问题

1.函数可以返回局部变量 当函数的局部变量作为函数的返回值时,其实是不知道是谁(是程序?)会自动生成一个变量的副本即拷贝作为函数的返回值,而原有的局部变量将被销毁. 注意函数不可以返回局部变量的地址或者某个指针,以为当函数运行完了(这里改咋说),系统会回收这块地址,因此这个地址里面 的东西也就没有意义了. 静态变量可以返回指针. 2. int a[] = {1, 2}; return a; 此时也会返回指针a的一个拷贝,若a的地址值为0x002345FC,则0x2345FC是能够成功返回的.当r