次のコードの出力が10
エラーではないのはなぜですか? object2
ぶら下がっているポインタではありませんか?
#include <iostream>
using namespace std;
int *method()
{
int object = 10;
return &object;
}
int main()
{
int *object2 = method();
cout << *object2;
}
ありがとう!
次のコードの出力が10
エラーではないのはなぜですか? object2
ぶら下がっているポインタではありませんか?
#include <iostream>
using namespace std;
int *method()
{
int object = 10;
return &object;
}
int main()
{
int *object2 = method();
cout << *object2;
}
ありがとう!
割り当てられなくなったメモリを指しているという点で、ダングリングポインターを取得し、その逆参照は未定義の動作を構成します。
この場合の動作はたまたま次のとおりです: アドレスはまだ有効であり、他のもので上書きされていません。
コンパイラは、ぶら下がっているポインターを逆参照する場合に備えて、すべてにゼロを書き込む時間を無駄にしませんが、valgrind などで実行するか、ポインターを取得してから逆参照するまでの間に他の関数呼び出しを実行することで、実際にぶら下がっていることを確認できます。 .
次のコード 10 の出力がエラーではないのはなぜですか?
未定義の動作は未定義であるためです。具体的には、 を含んでいたメモリを上書きすることは何も起こらないobject
ため、ぶら下がっているポインターを逆参照するまでに値は変更されていません。もう一度印刷してみると、何か違うものが見えるかもしれません。またはそうでない-未定義の動作は何でもできます。
object2
ぶら下がっているポインタではありませんか?
はい。ダングリング (または無効な) ポインターを逆参照すると、未定義の動作が発生するため、実行しないでください。
コンパイラの警告を有効にすることで、これを回避できるはずです。GCC では、特定の警告は によって有効になりますが、可能な限り多くの潜在的な間違いをキャッチ-Wreturn-local-addr
するために、少なくとも でビルドすることを強くお勧めします。-Wall -Wextra -Werror
gcc
との両方valgrind
がこれについてチェックします。
main.cpp: In function 'int* method()':
main.cpp:7:7: warning: address of local variable 'object' returned [-Wreturn-local-addr]
int object = 10;
^
main.cpp: In function 'int main()':
main.cpp:16:21: warning: 'object' is used uninitialized in this function [-Wuninitialized]
cout << *object2;
==22403== Conditional jump or move depends on uninitialised value(s)
==22403== at 0x4C99D61: std::ostreambuf_iterator<char, std::char_traits<char> > std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::_M_insert_int<long>(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, long) const (locale_facets.tcc:870)
==22403== by 0x4C9A2FC: std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::do_put(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, long) const (locale_facets.h:2475)
==22403== by 0x4CA5C1D: std::ostream& std::ostream::_M_insert<long>(long) (locale_facets.h:2336)
==22403== by 0x4007A3: main
==22403==
など... これはプログラミング エラーであり、コンパイラ エラーではありません。他の人が述べているように、それは未定義の動作です。コンパイラは、未定義の動作を診断する必要はありません。そのため、警告をオンにする必要があります。
次のコード 10 の出力がエラーではないのはなぜですか?
関数一時変数のアドレスを返しています。関数が返された後のそのようなアドレスの逆参照は、未定義の動作です。これは、奇妙なことが起こる可能性があり、自分でそれを見ることができることを意味します.
object2 はダングリング ポインターではありませんか?
はい、そうです。
あなたが書いたコードはエラーではなく、未定義の動作です。
これは未定義の動作です。g++ はそれについて警告します。
main.cpp:7:7: warning: address of local variable 'object' returned [-Wreturn-local-addr]
int object = 10;
http://coliru.stacked-crooked.com/a/ca3950756cefa9b7
そして、結果、正しい値、0 -> 無限大、クラッシュなどを取得できます。これはUndefined Behaviorと呼ばれます。
g++ を使用する場合は、次を追加することをお勧めします: -Werror=return-local-addr を追加すると、警告の代わりに適切なエラーが表示されます。
main.cpp:7:7: error: address of local variable 'object' returned [-Werror=return-local-addr]
int object = 10;
どのバージョンでこれを実行できるかはわかりません-これはg ++へのまったく新しい追加であると思います