C#のStackOverflowExceptionとは?原因と回避方法を解説
- システム
エンジニア - 'C#のStackOverflowExceptionとはなんですか?
- プロジェクト
マネージャー - C#のStackOverflowExceptionとはStackOverflowによる例外エラーを言います。原因や回避法を紹介します。
C#のStackOverflowExceptionとは?
今回は、C#のStackOverflowExceptionについて説明します。
StackOverflowExceptionとは、文字通りStackOverflowによる例外エラーのことです。StackOverflowとは、Stack(=入れ物)がある条件によって溢れ出てしまうことを指します。
C#では再帰処理によってStackOverflowExceptionが起きることが多いです。再帰処理については後ほど詳しく解説しますが、簡単に言うと、メソッドにて自身のメソッドを呼び出す処理のことです。
プログラムの設計ミスやコーディングミスによって自らのメソッドを呼び出す回数が多くなりすぎ、実行スタックが溢れ出てしまうことが原因です。
グラスに水を注ぐことをイメージしてください。当然ですが、グラスには注ぐことのできる水の量が決まっており、注ぐ量が多すぎればグラスから溢れ出てしまいます。プログラムの実行スタックも同じ話で、決まった量を超えることはできません。
この記事ではまず、StackOverflowExceptionの主要な原因である再帰処理とは何かを説明します。そして再帰処理においてStackOverflowExceptionが起きるサンプルプログラムを紹介し、回避方法について解説します。
また、StackOverflowExceptionオブジェクトの特性についても、簡単にですが説明します。C#のStackOverflowExceptionにお困りの方や、興味のある方はぜひご覧ください。
C#でStackOverflowExceptionが起きる原因と回避方法
はじめに、StackOverflowExceptionの主要な原因である再帰処理について解説します。
再帰処理とは、自らの処理を呼び出す処理が行われることを言います。以下の、C#で再帰処理をするサンプルプログラムのソースコードをご覧ください。メソッドからメソッドを呼び出して再帰処理を行っています。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
using System;
public class Sumple1
{
// 再帰処理
private static void Proc()
{
// 自らの処理を呼び出す
Proc();
}
// メイン処理
public static void Main()
{
Proc();
}
}
|
上記のサンプルプログラムでは、自らのメソッド(=Proc)を処理の中で呼び出しています。このような処理を再起処理と言い、階乗の計算や、ある数の総和を求める時などで使われることがあります。
例外エラーはプログラムが想定外の処理をした時に起きますが、StackOverflowExceptionも同様に、再帰処理にて呼び出すメソッドの回数が多すぎるという予期せぬ場合に生じます。
上記サンプルプログラムも、一度実行すると無限に同一メソッドを繰り返すため、StackOverflowExceptionが発生してしまいます。
そのため、詳細は後述しますが、StackOverflowExceptionが発生しないようにするために、再帰処理を実行する場合はメソッドから抜け出すための分岐処理を必ず組み込む必要があります。
StackOverflowExceptionを回避する
C#でStackOverflowExceptionが起きる主要な原因として挙げられる再帰処理について説明し、また再起処理でStackOverflowExceptionが起きる原因について説明しました。続いて、StackOverflowExceptionを回避する方法について説明します。
次のサンプルプログラムは、引数で与えられた整数nに対し、1以上かつn以下の整数の総和を求める処理のソースコードです。再起処理を使って総和を求めます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
using System;
public class Sumple2
{
// 総和計算メソッド
private static int Sum(int n)
{
int m;
// 0だった場合、ループを終了
// この処理がない場合、無限ループが発生し、StackOverflowExceptionが発生
if (n == 0) return 0;
// 自らのメソッドを呼び出す
m = Sum(n - 1);
// 再帰処理の結果を引数に加える
return n + m;
}
// メイン処理
public static void Main()
{
int totalNum = Sum(10);
// コンソール出力
Console.WriteLine("総和:{0}", totalNum);
}
}
|
実行結果は次のように出力されます。
総和:55
上記の再帰処理におけるポイントは、「n==0」で処理を終了している点です。この処理がなければ引数が負の数でも足し算を続けてしまい、処理が終了せず、StackOverflowExceptionが発生してしまいます。再帰処理の際は必ずサンプルプログラムのように、処理を終了するような分岐処理を入れましょう。
階乗計算サンプルプログラム
続いて、階乗計算のサンプルプログラムのソースコードを紹介します。階乗とは自然数nが0より大きい場合、n! = n * (n-1) * (n-2) * ・・・ * 3 * 2 * 1と計算され、n=0の場合は1となる計算です。
階乗計算は以下のソースコードのように再帰処理を使って計算できます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
using System;
public class Sumple3
{
// 階乗計算メソッド
private static int Factorial(int n) {
// n=0の場合、処理終了
// この処理がない場合、無限ループが発生し、StackOverflowExceptionが発生
if (n == 0) return 1;
return n * Factorial(n - 1);
}
// メイン処理
public static void Main()
{
int totalNum = Factorial(5);
// コンソール出力
Console.WriteLine("階乗:{0}", totalNum);
}
}
|
実行結果は次のように出力されます。
階乗:120
引数で与えられた自然数を再帰処理にて計算していますが、n=0の場合に処理を終了することで無限ループを回避し、StackOverflowExceptionの発生を防いでいます。
StackOverflowExceptionのtry-catch
.NET Framework Version2.0より以前のバージョンでは、StackOverflowExceptionオブジェクトをtry-catchブロックでキャッチできました。しかし.NET Framework Version2.0以降はtry-catchブロックでキャッチできません。
そのためC#でStackOverflowExceptionを防ぐためには、特定の条件によって処理を抜け出す分岐処理を再帰処理に組み込むようにしましょう。
- システム
エンジニア - StackOverflowの原因などがわかりました。
- プロジェクト
マネージャー - StackOverflowについての理解を深めて、回避方法など実践してみましょう。
C#のStackOverflowExceptionの原因と回避方法を知る!
いかがだったでしょうか。C#ではある処理でStack(=入れ物)がいっぱいになり、溢れてしまうとStackOverflowExceptionが発生します。また、Stackが溢れる主要な原因に再帰処理が挙げられます。
StackOverflowExceptionは.NET Framework Version2.0以降のバージョンでは、try-catchブロックでキャッチできません。
そこで、StackOverflowExceptionを回避するため、再帰処理の際は無限ループが発生しないように、条件に応じて処理を終了する分岐処理を入れる必要があります。
C#でプログラムを作成するうえでStackOverflowExceptionが発生した場合は、ぜひこの記事を参考にしてください。
FEnet.NETナビ・.NETコラムは株式会社オープンアップシステムが運営しています。
株式会社オープンアップシステムはこんな会社です
秋葉原オフィスには株式会社オープンアップシステムをはじめグループのIT企業が集結!
数多くのエンジニアが集まります。
-
スマホアプリから業務系システムまで
スマホアプリから業務系システムまで開発案件多数。システムエンジニア・プログラマーとしての多彩なキャリアパスがあります。
-
充実した研修制度
毎年、IT技術のトレンドや社員の要望に合わせて、カリキュラムを刷新し展開しています。社内講師の丁寧なサポートを受けながら、自分のペースで学ぶことができます。
-
資格取得を応援
スキルアップしたい社員を応援するために資格取得一時金制度を設けています。受験料(実費)と合わせて資格レベルに合わせた最大10万円の一時金も支給しています。
-
東証プライム上場企業グループ
オープンアップシステムは東証プライム上場「株式会社オープンアップグループ」のグループ企業です。
安定した経営基盤とグループ間のスムーズな連携でコロナ禍でも安定した雇用を実現させています。
株式会社オープンアップシステムに興味を持った方へ
株式会社オープンアップシステムでは、開発系エンジニア・プログラマを募集しています。
年収をアップしたい!スキルアップしたい!大手の上流案件にチャレンジしたい!
まずは話だけでも聞いてみたい場合もOK。お気軽にご登録ください。
C#新着案件New Job
-
システム開発/東京都新宿区/【WEB面談可/C#経験者/20代前半の方活躍中/経験1年以上の方活躍中】/在宅勤務
月給29万~34万円東京都新宿区(新宿駅) -
システム開発/東京都新宿区/【WEB面談可/C#経験者/20代後半~40代の方活躍中/経験年数不問】/在宅勤務
月給41万~50万円東京都新宿区(新宿駅) -
デバック、テスト項目の作成/神奈川県横浜市/【WEB面談可/C#経験者/20代前半の方活躍中/経験1年以上の方活躍中】/在宅勤務
月給29万~34万円神奈川県横浜市(桜木町駅) -
デバック、テスト項目の作成/神奈川県横浜市/【WEB面談可/C#経験者/20代後半~40代の方活躍中/経験年数不問】/在宅勤務
月給41万~50万円神奈川県横浜市(桜木町駅) -
基幹システム開発導入/東京都新宿区/【WEB面談可/C#経験者/20代前半の方活躍中/経験1年以上の方活躍中】/在宅勤務
月給29万~34万円東京都新宿区(西新宿駅) -
基幹システム開発導入/東京都新宿区/【WEB面談可/C#経験者/20代後半~40代の方活躍中/経験年数不問】/在宅勤務
月給41万~50万円東京都新宿区(西新宿駅)