Valgrindは、ヒープ上の空きオブジェクトへの残存参照を検出するのに便利です。ただし、スタック上のスコープ外の変数への参照が長引いているとは限りません。例えば:C++でスコープ外のスタック変数への参照を検出するにはどうすればよいですか?
#include <iostream>
struct CharHolder {
const char ch;
CharHolder(char _ch) : ch(_ch) {}
};
struct Printer {
const CharHolder& ref;
Printer(const CharHolder& _ref) : ref(_ref) {}
void print() {
std::cout << &ref << ": " << ref.ch << std::endl;
}
};
int main() {
// g++ -O0: prints 'x'
// g++ -O3: prints undefined character
Printer p1(CharHolder('x'));
p1.print();
// g++: prints undefined character
CharHolder* h = new CharHolder('x');
Printer p2(*h);
delete h;
p2.print();
}
最初の例では、p1
と、CharHolder('x')
をできるだけ早くp1
の構築が完了すると破壊されているので、プリンタが、外のスコープスタック変数への参照を保持しているものです。
p2
を持つ2番目の例は、p2
がprint()
でそれを参照しようとする前に、フリーであるヒープ変数への参照をプリンタが保持している例です。
Valgrindのは、第二の例文句:
==82331== Invalid read of size 1
==82331== at 0x400A8E: Printer::print()
==82331== by 0x400967: main
==82331== Address 0x5a1c040 is 0 bytes inside a block of size 1 free'd
==82331== at 0x4C2C2BC: operator delete(void*)
==82331== by 0x40095F: main
どのようにして、おそらくValgrindのようなツールを使用して、第一種のエラーを検出することができますか?
「valgrind」は静的解析ツールではありません。 – immibis
私はそれは渡された関数の引数よりも長く続くどのような方法でも、渡された参照を格納することは悪い考えであるということは、オブジェクトレッスン(pun)を意図していると思います。戻ったときに無効なオブジェクトを参照し、そのメンバーは役に立たなくなります。このような状況に対して警告を生成するために、コンパイラを作成する必要があるかもしれません。 –
@BlairHoughton - コンパイラが一時的な参照をパラメータとして渡す関数呼び出しをコンパイルするとき、コンパイラがコンパイルされていない可能性があるときに、呼び出された関数が渡された参照をどこかに格納することを、既知の記録された履歴の任意の時点で、呼び出された関数へのソースコードは、以前から始まっています。 –