質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

3回答

7714閲覧

visual studio c++デバッグ、”例外がスローされました”

bldtemporal

総合スコア35

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

1クリップ

投稿2021/12/23 11:02

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と言うように、計算により初期値が決まる変数だと思います)もかなりあるようですが、

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hoshi-takanori

2021/12/23 11:34

ソースコードを貼りましょう。
bldtemporal

2021/12/23 11:49

hoshi-takanori様、早速の応答有難うございます。ソースコードは大きすぎて、貼るのは無理です。お許し下さい。
int32_t

2021/12/23 12:53

まず間違いなく質問者さんのコードに問題がありますが、そのコードを開示していただかないと説明のしようがありません。MinGW-w64 で動いているように見えるのはたまたまでしょう。
bldtemporal

2021/12/25 01:57

int_32様、何時も参考になるアドバイスを有難うございます。 ・私のコードに問題があるのは、その通りです。修正の自己チャレンジをしたのち、開示の方法は考えてみます。 ・それから、MinGWで通るのは事実です。”例外スロー”と表示される変数はサブルーチン(関数)の引数です。3回呼び出すため引数にしていますが、サブルーチンの中でのみ扱っています。今回の作成(途中)で、MinGW(C & C++)では、そのような変数については、初期値設定をしないで、コンパイル & 実行が可能、なことが分かりました。
dodox86

2021/12/25 02:06

今現在、困っているであろう当事者の質問者さんの耳に届くかどうかわかりませんが、teratailは本来、デバッグのお手伝いを依頼するような場所ではないのです。 https://teratail.com/help#about-teratail に、以下の記載があります。 > teratailは技術に興味のある人達が集まって、質問と回答を通してお互いに知識や情報を交換・共有する場所です。 結果的に情報を小出しにして、一方的に質問者さん側に利があるような質問は控えましょう。答えようと思う閲覧者、回答者の負担が増えるばかりです。
bldtemporal

2021/12/25 11:18

dodox86様、初期化に関して、コンパイルの時にエラー無しになっているのに、デバックの時、再び問題になるようです。MinGWでも通らないはず、とのご意見もございます。多くの方のご意見により、原則を知りたいと思っているのです。こちらもその点では、経験した情報を発信しています。
fana

2021/12/28 07:25

> ソースコードは大きすぎて、貼るのは無理です その巨大なソースそのものでなくとも, 同一の現象が確認できる最低限のコードを別途作って示せばよいのではありませんか? (未初期化の問題を再現させるだけであればせいぜい10行程度のコードで済みそうに思いますが)
bldtemporal

2021/12/28 07:56

fana様、ご回答有難うございます。”初期値が無い”と言うエラー表示を修正しまあと、"例外フロー”の表示にかっわたのですが、良く見たら同じ変数についてでした。それで、全部を冒頭にもっていって初期化しています。400行近く増加しましたが、何とか結果が出てきました。まだ、チェックが不完全ですが、前進はしました。それで、初期化について、疑問を確かめるため、抜粋コードを作成して投稿しております。プログラムとしての貼り付けができなくて恐縮ですが、ご意見をお聞かせ頂けたら幸いです。
hoshi-takanori

2021/12/29 08:30

とりあえず、 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++ の仕組み上仕方ないんでしょうけど、いまいちな感じはありますね…。
bldtemporal

2021/12/29 11:45

hoshi-takanori様、初期化検討用コードまで示して頂いて有難うございます。ただ、今行っているのは少し違う組み立てです。mainからデータをサブルーチン(関数)に与え、サブルーチンで計算した結果(値)をmainで呼び出す、と言う組み立てです。頂いたコードに当てはめれば、mainでXを設定して&Xでsubに渡し、それを使った別の計算値をmainに呼び出す、と言うことです。投稿しましたコードではこれを実施して、初期値による影響を調査しています。初期値PAHD,V,FAHDを与えても、与えなくとも、サブルーチンでは正しく計算されてmainに帰されています(main中は&、サブ中は*です。また、subの最初では、これらはゴミです)。しかし、このコードをもう少し長く(間に別のサブルーチン等入れる)したときには、冒頭に初期値を入れなければ、初期値無しのエラーメッセージが表示されます。Prg冒頭部に初期値を入れなければならないとするケースの原則を知りたいのですが、良く分かりません。と言っても、とりあえず、全てのケースで入れておけば、問題ないとは言えます。
bldtemporal

2021/12/31 01:19

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++では必ず初期値を与えよ”と言うことですが、このような短いコードでは、与えても与えなくても、”どちらでも良い”、と感じます。ただ、間に複数のサブルーチンが入る(私の)長いコードでは、初期値を与えないとエラー表示されて計算できません。
hoshi-takanori

2022/01/01 01:49

ポインタを受け取る関数は、そのポインタが指す先の値に対して、 1. 読み出しのみ 2. 書き込みのみ 3. 読み書き両方 の 3 種類の操作を行う可能性があります。このうち 1 は const を付けることで区別できますが、2 と 3 を区別する方法は C や C++ には存在しません。(C# なら out と ref がありますが…。) 2 の場合 (書き込んでから読み出す場合も含めて)、元の値が不定であっても問題ありませんが、3 の場合 (読み出しを先に行う場合)、元の値が不定であれば読み出しは未定義動作となります。コンパイラには 2 と 3 の区別がつかないので、未定義動作にならないように気を付けるのはプログラマの責任となります。(Visual C++ の例外も、同一関数内での不定値しかチェックしてなくて、別の関数にポインタを渡した場合はその関数が値を代入したことにしているんだと思います。)
guest

回答3

0

全ての変数の初期化が必要と言うことなのでしょうか、

はい。

未初期化の変数を参照した場合、動作は未定義です。

「デバッグモードで引っかかる」のも、「そのまま動いてしまう」のも、さらには「不具合で落ちる」など、どんな動作をしようとも未定義な場合の動作として許容されています。

投稿2021/12/23 13:42

maisumakun

総合スコア145184

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

bldtemporal

2021/12/25 00:37

maisumakun様、参考になるご回答有難うございます。 ・確かにvisual studioの場合、初期値を設定してないと、”➀初期値が設定されていない”とエラー表示がある場合と、デバッグ時に”②例外がスローされました”と表示される場合があるようです。私の場合、➀では実行不能、②では計算ストップとなっています。どちらもサブルーチン(関数)の引数に関してです。 ところで、MigGW(C & C++)の場合には、引数にしているものの、サブルーチン内でのみ使う変数に関しては、上記のようなエラーにはならず、コンパイルと計算は何事も無く実行されます。 ・visual studioは本当に面倒ですね、私の場合、プログラムの最初に、x=0、y=aなど初期設定を1000程並べなければならないことになります。Compaq Fortranのように、初めて出てくる変数は、全て0に設定されているとか、何か良い方法は無いものでしょうか(無いのでしょうけれど)、
maisumakun

2021/12/25 07:24

> どちらもサブルーチン(関数)の引数に関してです。 具体的なコードを提示していただけませんでしょうか? > Compaq Fortranのように、初めて出てくる変数は、全て0に設定されているとか、何か良い方法は無いものでしょうか 配列にすれば一括での初期化は可能ですし、関数ローカルでない変数は宣言だけでゼロ初期化されます。
bldtemporal

2021/12/25 11:39

maisumakun様、貴重なアドバイス有難うございます。初期値に関しては、Xini=0,Yini=0のように,ほとんどがゼロですから、"配列化する" と言うのは、確かに良いアイデアと思います。最終的には実行して、コードを簡単化したい思います。コードの開示に関しましては、もう少し整理させて下さい。
guest

0

自己解決

・初期値設定の原則と"例外スロー"の発生について質問していましたが、下記の解決を得ました。
1.初期設定について
・下記コードで、初期値x=0を与えない場合、sub_f(double *x)(print)は、当然x=-9.256e+61とゴミになっています。一方、初期値x=0を与えた場合はx=0となります。しかしながら、計算の答えであるmainでは、どちらもx=6.283となって変わりません。sub_f()での、*Xの計算が初期値の設定となっているということ、解釈します。

C++

1#include <cstdio> 2#include<cstdlib> 3#define _USE_MATH_DEFINES 4#include <math.h> 5 6void sub_f(double * x); //--Prototype declaration 7 8int main(void) { 9double x; 10// x = 0; //-- xを初期化 してもしなくても良いようだ 11sub_f(&x); 12printf(" sub_f()での計算結果をmainでprint:x =%6.3f\ 13\n  (xを初期化してもしなくても同じ結果)\n\n", x); 14} 15// ================================= 16// **** Subruotine sub_f() **** 17void sub_f(double * x) { 18printf("\n sub_f()の最初でprint:*x =%11.3e\n\n", *x); 19*x=2*M_PI; 20}

2.例外スルーの発生原因について
・下記コードをでデバッグすると'y' is being used without being initialized.と表示されます。初期設定の位置を分かり易くするため、当該subroutineのsub_f2()の直前で実行したためです。これを止め、コードの冒頭で初期化実行すれば、正常に動作します。

#include <cstdio>
#include<cstdlib>
#define _USE_MATH_DEFINES
#include <math.h>

void sub_f1(double * x,double y,double d); //--Prototype declaration
void sub_f2(double
d); //--Prototype declaration

int main(void) {
// double x, y,d; //---これを生かして("//"を削除)正常動作
double x, d; //---例外スローを起こる.,正常動作には"//"とする 
x = 1;
// y = 2; //---これで”例外スロー”が起こる。"//"無しで初期化して正常動作
d = 0.1;
static int N = 0;
sub_f2(&d);
int i;
for (i = 0; i <= 2; i++) {
double y; //---正常動作とするには、ここ"//"とする。
//---下記までで、sub_f1()前にyを初期化する(1回通過)
static int kxy = 0;
if (kxy != 1) {
y = 2; /---これで”例外スロー”。"//"とすれば正常動作
kxy = 1;
}
//
**
sub_f1(&x,y,&d);
x = x + y + d;
printf("\n sub_f1(),sub_f2()での計算結果を呼び出したmainで計算結果
print:x=%5.1f, y=%4.1f, d=%4.1f, N=%d\n\n", x,y,d,N);
N = N + 1;
} //---”for”
}
// **** Subruotine sub_f() ****
void sub_f2(double
d) { *d = *d + 0.1; }
void sub_f1(double *x,double y,double *d) {
printf("\n sub_f()の最初でprint:*x =%5.1f, y =%4.1f\n", *x,y);
*x =*x+y; //---y が初期化されていないと,*x はゴミになるのでNG
printf("\n sub_f()の最後でprint:*x =%5.1f, y =%4.1f\n", *x,y);
}

投稿2022/01/01 06:57

bldtemporal

総合スコア35

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

全ての変数の初期化が必要と言うことなのでしょうか、

プログラムを正常に動作させるためには、変数は参照される前に必ず初期化されなければなりません。
文法上やコンパイラに許容されるかどうかを考えるのは正直無意味で、仕様云々の前にまずは変数の初期化が"正しく"行われているかを確認すべきです。

投稿2021/12/23 13:05

Serbonis

総合スコア581

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

bldtemporal

2021/12/28 06:38

maisumakun様、y_waiwai様;実コードを抜粋して編集し、
bldtemporal

2021/12/28 06:53

maisumakun様、y_waiwai様;実コードを抜粋して編集し、初期化を試してみました。PAHD,V,FAHDを冒頭に初期化しました。その状態では正常に動作しています。しかし、初期化しない状態(今"//"をつけています)で”デバッグしない状態で開始”を実行しても、同じ結果でした。ただし、初期化しない状態では、サブルーチンにPAHD,V,FAHDは渡されていないので、サブルーチン最初のprintfではゴミ状態です。その後サブルーチン中で計算されますので、mainでのprintfでは正しく出てきます。どんな条件でも最初出てくる前に初期化と言う定義とは外れていますが。正常ということになるのでしょうか。 ```C++ #include <iostream> int main() { std::cout << "#include<cstdio> #include<cstdlib> #include <fstream> #define _USE_MATH_DEFINES //--エラー"式が必要"を解消、#define M_PI 3.14のどちらかがあれば OK #include <math.h> //#define M_PI 3.14159265359 #include <time.h> //#pragma warning(disable : 4996) //--open,fscanf 関係の警告をoffにする, 無いとbe unsafeと出る using namespace std; int sub_HydDmp(double* PAHD, double* FAHD, double DHDP, double DHDC, double SHDP, \ double SSH1, double SSH2, double* ACRm, double* V); // **** Prototype declaration **** int main() { double PAHD, FAHD, V; //PAHD = 0.1013; //---初期化だが、これが無くても計算できる("//" にしてチェック) //V = 0; //---初期化だが、これが無くても計算できる("//" にしてチェック) //FAHD = 0; //---初期化だが、これが無くても計算できる("//" にしてチェック) ifstream ifs("Hyd_extDta.txt"); if (!ifs) { printf(" Hyd_extDta.txt: file open failure !!\n"); } // HydDmPDta_ext.txt : 6.000, 6.100, 3.00, 0.600, 0.300 //---これをtext Dataにする double DHDPINP, DHDCINP, DHDPRODINP, DSH1INP, DSH2INP, DHDP, DHDC, DHDPROD, DSH1, DSH2, ACR; char c; ifs >> DHDPINP >> c >> DHDCINP >> c >> DHDPRODINP >> c >> DSH1INP >> c >> DSH2INP; printf("\n Hyd_extDta.txt: DHDPINP=%9.6f, DHDCINP=%9.6f, DHDPRODINP=%8.5f, \ DSH1INP=%8.5f, DSH2INP=%8.5f\n", DHDPINP, DHDCINP, DHDPRODINP, DSH1INP, DSH2INP); DHDP = DHDPINP; DHDC = DHDCINP; DHDPROD = DHDPRODINP; DSH1 = DSH1INP; DSH2 = DSH2INP; const double SHDP = (pow(DHDP, 2) - pow(DHDPROD, 2)) * M_PI / 4; const double SSH1 = pow(DSH1, 2) * M_PI / 4; const double SSH2 = pow(DSH2, 2) * M_PI / 4; sub_HydDmp(&PAHD, &FAHD, DHDP, DHDC, SHDP, SSH1, SSH2, &ACR, &V); printf("\n main no saigo: DHDP=%10.3e(cm), SHDP=%10.3e(cm), SSH1=%10.3e(cm^2), \ SSH2=%10.3e(cm^2), V=%4.1f(m/s), FAHD=%10.3e(N)\n", DHDP, SHDP, SSH1, SSH2, V, FAHD); //   //---Subroutine 呼び出し return 0; } // ==================================================================================== int sub_HydDmp(double* PAHD, double* FAHD, double DHDP, double DHDC, double SHDP, \ double SSH1, double SSH2, double* ACR, double* V) { printf("\n sub no saisho: DHDP=%10.3e(cm), SHDP=%10.3e(cm), SSH1=%10.3e(cm^2), \ SSH2=%10.3e(cm^2), *V=%4.1f(m/s), *FAHD=%10.3e(N)\n", DHDP, SHDP, SSH1, SSH2, *V, *FAHD); *V = 4.0; *ACR = (pow(DHDC, 2) - pow(DHDP, 2)) * M_PI / 4 + SSH1 + SSH2; *PAHD = pow((SHDP * (*V) / (0.8 * (*ACR) * 8.4)), 2) + 1.033; *FAHD = 0.75 * (*PAHD - 1.033) * SHDP * 9.807; *PAHD = *PAHD * 0.09807; return 0; }" << std::endl; } ```
int32_t

2021/12/31 01:54

上記のコードで「例外がスローされました」が再現するということでしょうか? main() が2つあるのはどういうことですか。このコードを質問文に入れていただけますか。
bldtemporal

2021/12/31 02:37

int32_t様、何時もご回答ありがっとうございます。 1. ”上記のコードで例外がスローされました。” ・上記のコードでは、”エラー表示”も”例外スロー”の表示もされず正常に動作します。初期化が無いのに、エラー表示されないことに対する疑問です。C++では必ずコード冒頭での変数初期化が必要である、と強く言われますが、そうでないケースもあるのではないでしょうか、但し、全部に入れた方が無難、と言うのは事実のようです。 2. "mainが2か所ある。” ・申し訳ありません。以前どなたかに、”この間にコードを入れれば良い”と教わった通りにしたら、こうなりました。最初の3行(std:: まで)、及び最後から2行目(}"<<std::endl;)は無効です。 3. ”このコードを質問文に入れて下さい” ・???(何のことでしょうか)
bldtemporal

2021/12/31 02:41

int32-t様、「追伸」:本日hoshi-takanori様のご回答に対しても、同様の返信をしておりますので、参考にして下さるようお願い致します。
int32_t

2021/12/31 04:10

1. 期待どおり動くコードを提示されても、何が悪かったのか指摘するのは困難です。参照する前に初期化か代入しておけば問題はありません。 3. 長いコードを回答のコメントに書かずに、もとの質問文を編集して追記してください。
bldtemporal

2021/12/31 04:22

int32_t様、早速のご回答有難うございます。 ・残念ながら、投稿したような短いコードでは、”初期値が必要”、or ”例外スロー”の状況を再現できないので、質問編集もできません。何度も申しますが、”くさい”とにらんでいるのは、対象変数を含むサブルーチンの前に複数のサブルーチンがあることです。短いコードで、そのような状況を作り出せるか、チャレンジしてみます。
bldtemporal

2022/01/01 06:47

int32_t様、ご教示の意欲有難うございます。先に返信投稿しました件ですが、結局のところ、*Xはsub_f()で最初に参照されるのですが、sub_f()で計算されて返されるので、初期設定したことになっているようです。ですから冒頭でのXの初期設定は不要となっている、と言うことですね。常識かも知れませんが、それから、例外スローについては、発生を再現し、どのような場合に発生するのか理解しました。自己解決の欄にポストしますので、見て頂ければ幸いです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問