昨天晚上,SIST 的宋教授在 SIST 一个官方研招群里分享了一个 Bug,如下图:

Bug:返回局部对象的引用或指针

代码如下:

Bug:返回局部对象的引用或指针

一开始我觉得没问题啊,怎么会出现段错误呢?并且 new 怎么可能不是 new 一个 heap 对象?(后来得知教授的意思是 ss 无法 new 到堆上让他保持)

之所以有这样的疑问,也是因为虽然我经常用 C++,但是多数都是用来做 OJ 题目,所以并不常用工程项目中所用到的一些用法,也就缺乏这方面的经验。

宋教授告诉我是因为 ObjectLifetime,可是我一下子并没有想明白为什么,于是尝试去还原一下 Bug,如下是还原后的代码及编译情况:

Bug:返回局部对象的引用或指针
Bug:返回局部对象的引用或指针

在不加 static 的情况下,产生了段错误,不过直接原因并不像有的学长说的那样,是因为返回了 new 对象,这只是间接原因,真正的原因是 ss,因为 ss 是一个 std::istream 对象,不能拷贝只能引用,所以在 Reader(ss) 里传递过去了 ss 的引用,这也是我们题目中所说的返回局部对象的引用的 Bug 之所在,不过为什么如此这般就是 Bug 呢?

在这里我们需要简单说一些局部对象的生命周期(Lifetime),我们在函数 make_reader() 中声明的两个对象 s1ss 都是局部对象,在这个函数结束后,这两个局部对象的生命周期也就结束了,被销毁了。待到我们调用这个函数返回的 Reader 中的 ss 引用时,很容易发现 ss 本体都已经被销毁了,引用还有什么存在的意义呢,如果非要说他存在的意义,那就是造成段错误。由于局部对象是放在段里的,所以引用指向的也是段里,当段里的对象被销毁时,引用也就造成了段错误。

那么这种问题怎么解决呢?

根据刚才的分析是因为局部对象生命周期结束导致的,那么我们可以想办法改变他的生命周期,方法之一就是 static,这样他的生命周期就贯穿整个程序,也就不会出现段错误了。

不过个人感觉这样做欠妥,因为加上 static 的时候他只会在第一次调用时真正的执行,后续的调用时都会沿用上一次的状态,这样是否会造成混乱呢?

暂时没有想到更好的解决方案,欢迎大家指点。

返回局部对象的引用的 Bug 我们可能已经讲得十分清楚了,指针同理。

相关文章: