C++に傷つけられた経験

1644 ワード

変換元:https://www.zhihu.com/question/310052411/answer/620132502
先日、エラーのC++プログラムを見せてもらいました.ここでは間違いの部分だけをあげます.
string s1 = string("string1");
string s2 = string("string2");
const char* p1 = s1.substr(1).data();    // substr(1)           1      
const char* p2 = s2.substr(1).data();
cout << p1 << p2 << endl;

短い6行のプログラムで、プログラムの出力を当ててみましょう.一般人の第一反応はtring 1 tring 2だろうと思います.結局、プログラムはこの6行だけなので、何か間違いがありますか?
でもいいえ!当時プログラムの出力はtring 2 tring 2でした!私はどうしてその時を言ったのですか?台の機械を交換したのでこの問題はまたなくて、出力はまた正常なtring 1 tring 2になりました!
この6行のコードに直面して、私は考えて、長い間デバッグしました.最終的に問題点が見つかりました.
s1.substr(1)は、s 1を一時的に格納するサブ列を作成する.次にdata()関数を用いてこのサブ列のメモリポインタを取得した.今まで、すべて正常でした.
しかし!次の行に着きました!このs 1サブストリングを格納する文字列オブジェクトは、解析されます!コンパイラはこれが一時的なオブジェクトであることを発見したので、ブロックが終わるまで待たずに、直接それを解析しました.その後、この一時オブジェクトのメモリが解放され、新しいオブジェクトs 2が確立する.substr(1)どこに構築されたか当ててみましょうか?そう、s 1です.substr(1)が死んだ場所==そこでdata()を呼び出し,p 1と同じポインタを得たが,メモリのデータはs 2のサブストリングに変更された.
私の推測では、プログラムを修正しました.
string s1 = string("string1");
string s2 = string("string2");
ss1 = s1.substr(1);
ss2 = s2.substr(1);
const char* p1 = ss1.data();    // substr(1)           1      
const char* p2 = ss2.data();
cout << p1 << p2 << endl;

やはり問題は二度と現れなかった.そして私はこの結論を持って資料を調べて、同じ内容の文章を見つけました.
https://blog.csdn.net/stpeace/article/details/46461167​
プログラムは異なりますが、主な内容は同じです.一時オブジェクトはブロックが終わるまで待たずに即座に解析されます.
 
しかし、これはまだこの問題が最も恐ろしい場所に着いていない.この問題が一番怖いのは、私が答えを編集している間に、この間違ったプログラムが当時間違っていた機械で同じコンパイラでコンパイルされ、問題が再現されなくなったことです.
大規模なプログラムにこのようなプログラムが現れたら、プログラマーはどのくらいの午後を費やしますか?