visual studio c++で、エラーメッセージの”初期化してないローカル変数・・が使用されます”と表示されたので、その全てを初期化して、更に”デバッグ開始”を実行したところ、次のような変数”QH3HOT"について表示されました。
”例外がスローされました”
Run-Time Check Failure #3 - The variable 'QH3HOT' is being used without being initialized.
・visual studio C++では、エラーメッセージが出なくとも、このような”例外スロー”で止まってしまいます。全ての変数の初期化が必要と言うことなのでしょうか、
・どこに仕様の違いがあるのか分かりませんが、同じプログラムでも、MinGW-w64による ”C”,"c++"では、初期化しないで良い場合(X=a+bと言うように、計算により初期値が決まる変数だと思います)もかなりあるようですが、
ソースコードを貼りましょう。
hoshi-takanori様、早速の応答有難うございます。ソースコードは大きすぎて、貼るのは無理です。お許し下さい。
まず間違いなく質問者さんのコードに問題がありますが、そのコードを開示していただかないと説明のしようがありません。MinGW-w64 で動いているように見えるのはたまたまでしょう。
int_32様、何時も参考になるアドバイスを有難うございます。
・私のコードに問題があるのは、その通りです。修正の自己チャレンジをしたのち、開示の方法は考えてみます。
・それから、MinGWで通るのは事実です。”例外スロー”と表示される変数はサブルーチン(関数)の引数です。3回呼び出すため引数にしていますが、サブルーチンの中でのみ扱っています。今回の作成(途中)で、MinGW(C & C++)では、そのような変数については、初期値設定をしないで、コンパイル & 実行が可能、なことが分かりました。
今現在、困っているであろう当事者の質問者さんの耳に届くかどうかわかりませんが、teratailは本来、デバッグのお手伝いを依頼するような場所ではないのです。
https://teratail.com/help#about-teratail
に、以下の記載があります。
> teratailは技術に興味のある人達が集まって、質問と回答を通してお互いに知識や情報を交換・共有する場所です。
結果的に情報を小出しにして、一方的に質問者さん側に利があるような質問は控えましょう。答えようと思う閲覧者、回答者の負担が増えるばかりです。
dodox86様、初期化に関して、コンパイルの時にエラー無しになっているのに、デバックの時、再び問題になるようです。MinGWでも通らないはず、とのご意見もございます。多くの方のご意見により、原則を知りたいと思っているのです。こちらもその点では、経験した情報を発信しています。
> ソースコードは大きすぎて、貼るのは無理です
その巨大なソースそのものでなくとも,
同一の現象が確認できる最低限のコードを別途作って示せばよいのではありませんか?
(未初期化の問題を再現させるだけであればせいぜい10行程度のコードで済みそうに思いますが)
fana様、ご回答有難うございます。”初期値が無い”と言うエラー表示を修正しまあと、"例外フロー”の表示にかっわたのですが、良く見たら同じ変数についてでした。それで、全部を冒頭にもっていって初期化しています。400行近く増加しましたが、何とか結果が出てきました。まだ、チェックが不完全ですが、前進はしました。それで、初期化について、疑問を確かめるため、抜粋コードを作成して投稿しております。プログラムとしての貼り付けができなくて恐縮ですが、ご意見をお聞かせ頂けたら幸いです。
とりあえず、
int main()
{
int x;
printf("x = %d\n", x);
}
くらいの単純なプログラムで未初期化ローカル変数の挙動を確認してみては。
(Visual Studio 2022 で確認してみましたが、Debug ビルドではコンパイルエラー C4700 になったので、#pragma warning(disable: 4700) でエラーを無視したら実行時例外が出ました。ちなみに Release ビルドではエラーは出ずに x = 0 と表示されました。)
さらに、
void f(int* x)
{
// 何もしない
}
int main()
{
int x;
f(&x);
printf("x = %d\n", x);
}
のように x のポインタを引数にして適当な関数を呼ぶと、Debug ビルドでもエラーが出ずに x = -858993460 のようなゴミが表示されました。
初期化されてない int や double やコンストラクタを持たない構造体などの POD (Plain Old Data) へのアクセスは未定義動作なので、x = 0 でも x = -858993460 でも例外でも PC が爆発しても言語仕様に反してはいませんが、ポインタを関数に渡すと例外が出ないってのは C++ の仕組み上仕方ないんでしょうけど、いまいちな感じはありますね…。
hoshi-takanori様、初期化検討用コードまで示して頂いて有難うございます。ただ、今行っているのは少し違う組み立てです。mainからデータをサブルーチン(関数)に与え、サブルーチンで計算した結果(値)をmainで呼び出す、と言う組み立てです。頂いたコードに当てはめれば、mainでXを設定して&Xでsubに渡し、それを使った別の計算値をmainに呼び出す、と言うことです。投稿しましたコードではこれを実施して、初期値による影響を調査しています。初期値PAHD,V,FAHDを与えても、与えなくとも、サブルーチンでは正しく計算されてmainに帰されています(main中は&、サブ中は*です。また、subの最初では、これらはゴミです)。しかし、このコードをもう少し長く(間に別のサブルーチン等入れる)したときには、冒頭に初期値を入れなければ、初期値無しのエラーメッセージが表示されます。Prg冒頭部に初期値を入れなければならないとするケースの原則を知りたいのですが、良く分かりません。と言っても、とりあえず、全てのケースで入れておけば、問題ないとは言えます。
hoshi-takanori様
・ご教示のコードを、実行している下記の形式に組み換えさせて頂きました。
```C++
#include <cstdio>
#include<cstdlib>
#define _USE_MATH_DEFINES
#include <math.h>
void sub_f(double * x); //--Prototype declaration
int main(void) {
double x;
// x = 0; //-- xを初期化 してもしなくても良いようだ
sub_f(&x);
printf(" sub_f()での計算結果をmainでprint:x =%6.3f\
\n (xを初期化してもしなくても同じ結果)\n\n", x);
}
// =================================
// **** Subruotine sub_f() ****
void sub_f(double * x) {
printf("\n sub_f()の最初でprint:*x =%11.3e\n\n", *x);
*x=2*M_PI;
}
```
・初期値x=0を与えない場合、sub_f(double *x)でのprintは、当然
x=-9.256e+61とゴミになっています。一方、初期値x=0を与えた場合はx=0となります。しかしながら、計算の答えであるmainでは、どちらもx=6.283となって変わりません。
・”c++では必ず初期値を与えよ”と言うことですが、このような短いコードでは、与えても与えなくても、”どちらでも良い”、と感じます。ただ、間に複数のサブルーチンが入る(私の)長いコードでは、初期値を与えないとエラー表示されて計算できません。
ポインタを受け取る関数は、そのポインタが指す先の値に対して、
1. 読み出しのみ
2. 書き込みのみ
3. 読み書き両方
の 3 種類の操作を行う可能性があります。このうち 1 は const を付けることで区別できますが、2 と 3 を区別する方法は C や C++ には存在しません。(C# なら out と ref がありますが…。)
2 の場合 (書き込んでから読み出す場合も含めて)、元の値が不定であっても問題ありませんが、3 の場合 (読み出しを先に行う場合)、元の値が不定であれば読み出しは未定義動作となります。コンパイラには 2 と 3 の区別がつかないので、未定義動作にならないように気を付けるのはプログラマの責任となります。(Visual C++ の例外も、同一関数内での不定値しかチェックしてなくて、別の関数にポインタを渡した場合はその関数が値を代入したことにしているんだと思います。)
回答3件
あなたの回答
tips
プレビュー