前几天帮人看了个出错的C++程序。我这里只给出错的部分好了:
短短的六行程序,大家猜一下程序的输出。我想一般人的第一反应应该是tring1tring2吧。毕竟程序就这六行,能出什么错呢?
然而不!当时程序的输出是tring2tring2!而我为什么说当时呢?因为换了台机器这个问题又没有了,输出又变成了正常的tring1tring2!
面对这六行代码,我思考,调试了很久。最终发现了问题所在:
s1.substr(1)创建了一个临时对象存储s1的子串。然后我们用data()函数获取了这个子串的内存指针。到目前为止,一切正常。
然而!到了下一行!这个存储s1子串的字符串对象,被析构了!因为编译器发现这是个临时对象,于是没有等到块结束再析构,而是直接立即析构了它!然后这个临时对象的内存被释放了,而我们此时又建立了一个新的对象s2.substr(1),猜猜它被建立到哪了?没错,就是s1.substr(1)死的地方= =于是我们又调用data(),得到了和p1一样的一个指针,而此时内存的数据已经被修改为s2的子串了。
按照我的这个猜想,我修改了一下程序:
果然问题没有再出现。然后我带着这个结论去查了一下资料,发现一篇相同内容的文章:
程序不太一样,但是主要内容是一样的:临时对象会被当即析构,而不会等到块结束。
但是这还没有到达这个问题最恐怖的地方。这个问题最恐怖的地方在于,就在我编辑回答的这个时间,这段错误的程序在当时出错的机器上用相同的编译器编译,问题复现不出来了!
如果在某个大型程序中出现这么一段程序,会花费编程人员多少个下午?