下記のように一度変数を保持させたあとにスコープ外にいった場合
x.xの値を参照するのは危険な行為になるのでしょうか?
c++
1class X 2{ 3public: 4 int* x; 5}; 6 7using std::cout; 8 9int main() 10{ 11 X x; 12 { 13 int n = 111; 14 x.x = &n; 15 16 cout << x.x << "\n"; 17 } 18 19 cout << x.x << "\n"; 20 21 getchar(); 22}
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
回答6件
0
int n = 111; ラインは、変数を一時的なスタックにアサインします。この変数は、仮想メモリ上のアドレスを持ち、ポインターの値として、x.xに保存されます。一方、このスタックは {で始まるラインから、}で終わるラインまでが有効で、ライン19ではもう存在しません。そのため、ライン19は意味を持たないポインターの値をプリントすることになってしまいます。コンパイラーは間違った使い方をしていると警告を出すのでしょう。
投稿2026/02/11 00:18
総合スコア273
0
危険だと思いますが、実際のところ、どうなるか、コンパイラ次第と思いますが、
スタックメモリ上のローカル変数ですが、関数内に新たなローカル変数があるからといって、新たにスタックメモリを確保するのではなく、関数の頭で一括で確保し関数を抜けるところで一括で返します。
よって実際のところ、スコープを抜けたところでも関数を抜けるまでは、そのエリアは確保されていますが仕様ではありませんので保障はありません。で、一応動く。
コンパイラ次第なんて危なくて使う気しないと思います。一度大丈夫でも最適化などで変わってしまう可能性もある。
投稿2026/02/09 23:12
総合スコア366
0
Cppcheck - A tool for static C/C++ code analysis という、静的解析(static analysis)を行うツールがあります。これで質問文にあるソースコードを解析してみると、以下の様なエラー(invalidLifetime)が報告されます。
sh
1$ cppcheck invalid_life_time.cc 2 3invalid_life_time.cc:19:11: error: Using object that points to local variable 'n' that is out of scope. [invalidLifetime] 4 cout << x.x << "\n"; 5 ^ 6invalid_life_time.cc:16:11: note: Address of variable taken here. 7 x.x = &n; 8 ^ 9invalid_life_time.cc:15:9: note: Variable created here. 10 int n = 111; 11 ^
また、スコープ外から参照する対象をポインタアドレスではなく実体の値に変更してから gcc の Address Sanitizer でチェックすると、stack-use-after-scope | Microsoft Learnというエラーが検出されることが判ります。
c++
1 cout << *x.x << "\n"; 2 //cout << x.x << "\n"; 3 getchar();
sh
1$ g++ --version 2g++ (Ubuntu 15.2.0-4ubuntu4) 15.2.0 3 4$ g++ -fsanitize=address -Wall -Wextra -g invalid_life_time.cc -o invalid_life_time && ../invalid_life_time 5 6==569735==ERROR: AddressSanitizer: stack-use-after-scope on address 0x72b421200030 at pc 0x5770c8ae03f8 bp 0x7fffb42ba030 sp 0x7fffb42ba020 7READ of size 4 at 0x72b421200030 thread T0 8 #0 0x5770c8ae03f7 in main invalid_life_time.cc:19 9 #1 0x76b42342a574 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58 10 #2 0x76b42342a627 in __libc_start_main_impl ../csu/libc-start.c:360 11 #3 0x5770c8ae01e4 in _start (invalid_life_time+0x11e4) (BuildId: 282ae10eecaab9190cb0f4ec5c1d7b5458b25ac3) 12 13Address 0x72b421200030 is located in stack of thread T0 at offset 48 in frame 14 #0 0x5770c8ae02b8 in main invalid_life_time.cc:12 15 16 This frame has 2 object(s): 17 [48, 52) 'n' (line 15) <== Memory access at offset 48 is inside this variable 18 [64, 72) 'x' (line 13) 19HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork 20 (longjmp and C++ exceptions *are* supported) 21SUMMARY: AddressSanitizer: stack-use-after-scope invalid_life_time.cc:19 in main 22
投稿2026/02/08 06:04
総合スコア21695
0
寿命を終えたオブジェクトを指していたポインタは無効 (invalid) であり、無効なポインタを使用した効果は未定義です。 たとえポインタが指す先のオブジェクトにアクセスしなくてもポインタを使おうとすること自体が未定義の効果であると解されます。
投稿2026/02/08 05:25
編集2026/02/08 05:32総合スコア5852
2026/02/09 00:56 編集
0
xは初期化しておいたほうがよいでしょう。
X x = {};
n自体はスコープを外れると参照できなくなりますが、その111が入っているアドレスはx.xに代入されるので、問題無いと思います。
投稿2026/02/08 04:33
総合スコア1747
0
自己解決
たくさんのコメントありがとうございました。
コンパイルエラーや動作に問題がありませんでしたので気にしていませんでしたが
よろしくない書き方ということが分かりました。
投稿2026/02/14 09:02
総合スコア76
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。