Stack Overflow
出典: フリー百科事典『ウィキペディア(Wikipedia)』 (2025/04/29 03:58 UTC 版)
| |
|
| URL | stackoverflow.com(英語) ja.stackoverflow.com(日本語) |
|---|---|
| 言語 | 英語、スペイン語、ロシア語、ポルトガル語、日本語 |
| タイプ | 知識マーケット |
| 運営者 | Stack Exchange, Inc. |
| 設立者 | ジョエル・スポルスキ、ジェフ・アトウッド |
| 営利性 | あり |
| 登録 | 任意、OpenID |
| 開始 | 2008年5月 |
| 現在の状態 | オンライン |
|
ライセンス
|
|
Stack Overflow(スタックオーバーフロー)はStack Exchange Networkの一つ[2][3]で、コンピュータや情報技術、特にプログラミング技術に関するナレッジコミュニティである。サービスはジェフ・アトウッドとジョエル・スポルスキ[4][5]によって2008年に開始された。Stack Overflowという名称は、2008年4月、Atwoodが運営するブログの読者による投票で決定された[6]。
本サービスはコンピュータ・プログラミングの広範囲なトピックを扱っていることが特色である[7][8][9]。ウェブサイトは質問と回答を行う機能、またそれらに対する評価付け、wikiやdiggに似た文書の編集機能を備えており[10]、ユーザの活発な参加を促している。Stack Overflowのユーザは良質な回答を行うことによって、評価ポイントや「バッジ」を得ることができ[11]、本サービスは伝統的なQ&Aサイト・フォーラムにゲーミフィケーションを施したものと言える。全てのユーザによる記述内容はクリエイティブ・コモンズライセンス下にある[1][12]。
2019年3月時点で、Stack Overflowの登録ユーザは約1020万人であり、2600万を超える質問が存在する[13]。質問に付加されたタグによると、Stack Overflowの一般的なトピックは、JavaScript、Java、C#、PHP、Android、Python、jQuery、HTML、C++等である[14][15]。
2014年12月に日本語版であるスタック・オーバーフローが開設された[16]。2019年3月時点で、スタック・オーバーフローの登録ユーザは約2万人であり、2万を超える質問が存在する[13]。質問に付加されたタグによると、スタック・オーバーフローの一般的なトピックは、Python、JavaScript、Swift、iOS、Ruby on Rails、PHP、Android、Java、C#等である[17][15]。
脚注
- ^ a b What is the license for the content I post? - Help Center - Stack Overflow
- ^ “Stack Exchange Network Legal Links”. Stack Exchange. 2012年1月2日閲覧。
- ^ Stack Overflow Internet Services, Inc. (2010年6月8日). “Stack Exchange API”. Stack Apps. 2010年6月8日閲覧。
- ^ Jeff Atwood (2008年4月16日). “Introducing Stackoverflow.com”. Coding Horror. 2009年3月11日閲覧。
- ^ Jeff Atwood (2008年9月16日). “None of Us is as Dumb as All of Us”. Coding Horror. 2009年3月11日閲覧。
- ^ Jeff Atwood (2008年4月6日). “Help Name Our Website”. Coding Horror. 2009年6月15日閲覧。
- ^ Alan Zeichick (2009年4月15日). “Secrets of social site success”. SD Times. 2009年4月16日閲覧。
- ^ “Spolsky's Software Q-and-A Site”. Slashdot (2008年9月16日). 2009年5月23日閲覧。
- ^ Joel Spolsky (2009年4月24日). “Google Tech Talks: Learning from StackOverflow.com”. YouTube. 2009年5月23日閲覧。
- ^ Jeff Atwood (2008年9月21日). “The Gamification”. Coding Horror Blog. 2011年1月24日閲覧。
- ^ “FAQ: What is Reputation?”. Stack Overflow. 2010年1月19日閲覧。
- ^ Creativecommons.org
- ^ a b “All Sites - Stack Exchange”. Stack Overflow. 2019年3月25日閲覧。
- ^ a b 上位9項目前後までを記載。
- ^ プログラマー向けのQ&Aサイト「Stack Overflow」、日本語版が一般公開 INTERNET Watch 2014-12-17
スタックオーバーフロー
(Stack_Overflow から転送)
出典: フリー百科事典『ウィキペディア(Wikipedia)』 (2025/12/04 13:29 UTC 版)
|
|
この記事は検証可能な参考文献や出典が全く示されていないか、不十分です。 (2025年12月)
|
スタックオーバーフロー (英: stack overflow) は、コンピュータプログラムにおいて、コールスタック領域の限界を超えたデータプッシュにより発生する、バッファオーバーフローの一種である。スタックバッファオーバーフロー (英: stack buffer overflow) とは別の概念である。
概要
一般的なプログラムの実行環境では、サブルーチン(関数、プロシージャ、あるいはメソッドとも)の呼び出しに関する情報を格納するためのスタックメモリ領域(コールスタック)が確保される。サブルーチン呼び出しのたびにデータがスタックに積まれ(プッシュ)、サブルーチンが終わって制御フローが呼び出し元に戻るとスタックからデータが降ろされる(ポップ)。また、コールスタックはサブルーチン内でのみ使用されるローカル変数を確保するための領域でもある。オペレーティングシステム (OS) や実行オプションにもよるが、コールスタックに格納できる情報量には上限がある。コールスタックに蓄積されるデータ量が限界を超えるとスタックは「オーバーフロー」し、未定義動作を引き起こす。OSにもよるが、プログラム側で対策をとっていなければ通常はプロセスがクラッシュしてしまう。ただし、スタックオーバーフローの原因となりうるコードパターンは比較的限定されている。
スタックオーバーフローの発生原因のうち、最も多いのはサブルーチンの再帰呼び出しによる無限ループ(無限再帰)である。また、ソースコードの設計上は無限再帰ではなく、終了条件を決めて有限回数で打ち切るような有限再帰になっていたとしても、再帰呼び出しの階層数が深すぎると実行環境におけるコールスタックの上限を超えてしまい、スタックオーバーフローとなってしまう場合もある。ただし、末尾最適化を実装したプログラミング言語では、末尾再帰の形で書かれたサブルーチンをループへ展開することができ、スタックオーバーフローは起こらなくなる。フラットなループ処理に変換されることで、再帰呼び出しによりスタックを消費することが無くなるからである。なお、再帰ではないサブルーチン呼び出しであっても、呼び出し階層数が深すぎる場合には、やはりスタックオーバーフローが起こりうる。
次によくある原因としては、スタック上に巨大な配列を確保しようとすることである。コールスタックに格納できる情報量には上限があるため、巨大なサイズのローカル変数を定義するのではなく、ヒープ領域などを明示的に利用すべきである。配列1つのサイズがそれほど大きくなくても、再帰呼び出しなどでサブルーチンの呼び出し階層が深くなることによってコールスタックを食いつぶし、スタックオーバーフローを引き起こすこともある。
C/C++ での例
再帰による無限ループ
/* 関数の戻り値が int の場合、C言語では前方宣言や前方定義がなくてもコンパイル可能だが、C++では前方宣言あるいは前方定義が必要。 */
int g(void);
int f(void) {
return g();
}
int g(void) {
return f();
}
関数 f() は関数 g() を呼び出しているが、g() もやはり f() を呼び出している。交互の呼び出しは終わることがなく、最終的にはスタックオーバーフローが発生する。以下のような終了条件のない自己再帰も無限再帰となる。
int foo(void) {
return foo();
}
巨大な配列をスタックに配置した場合
C/C++において、関数内で定義されるローカル変数(ブロックスコープを持つ変数)は既定で(staticキーワードで修飾しない限り)自動変数となり、ブロックを抜けることで自動的に変数の寿命が尽きてメモリが解放される自動記憶域期間を持つ[1]。言語仕様では自動変数の実装形態について特に規定されていないが、一般的にはコールスタックを利用して実装される。
システムに実装されているメインメモリの容量にかかわらず、各プログラムのスタック領域のサイズはスレッドごとに既定でせいぜい数MiB程度[2][3][4][5][6][7]であり、大容量の配列を確保するのには向いていない。コンパイルオプションやスレッドの起動時オプションなどでスタックサイズの既定値を変更できる環境もあるが、スタックサイズを増やすにつれてプロセス内で起動可能なスレッドの最大数が減少することになる。
#include <stdio.h>
int main(void) {
int ary[1000 * 1000 * 1000]; /* 配列が大きすぎる */
printf("Hello!\n"); /* &"Hello!\n" のプッシュがスタックオーバーフローとなる */
}
この場合は、
#include <stdio.h>
int ary[1000 * 1000 * 1000];
int main(void) {
printf("Hello!\n");
}
または
#include <stdio.h>
int main(void) {
static int ary[1000 * 1000 * 1000];
printf("Hello!\n");
}
のように配列を静的領域に移動するか、あるいは malloc などを使ってヒープ領域に動的確保すればスタックオーバーフローは回避できる。ただし32ビット環境ではアドレス空間の上限が4 GiBであるため、上記のように巨大な配列を静的確保しようとするとプログラムの起動が失敗してしまう可能性がある。通例、システムが利用できる空きメモリの量は必ずしも定かではないので、64ビット以上の環境であっても、実行時の動的メモリ確保と成否チェックを行なうことが望ましい。
#include <stdio.h>
#include <stdlib.h>
int main(void) {
/* malloc() 関数が失敗した場合は NULL ポインタが返却されるため、実際にメモリ領域を利用する前に NULL チェックをする必要がある */
int *ary = (int *)malloc(sizeof(int) * (size_t)(1000 * 1000 * 1000));
printf("Hello!\n");
/* NULL に対して free() 関数を実行しても何も起こらないことが C/C++ 規格で保証されているため、NULL チェックは不要 */
free(ary);
}
JavaやC#/VB.NETのような仮想マシンベースの実行環境を持つ言語では、OSではなく仮想マシンによって管理されているヒープ領域を使うことによって、動的メモリ確保のオーバーヘッドを低減している。これらの言語では、通常の(言語組み込みの)配列は常にヒープ領域に割り当てられるため、実行時にメモリ不足の例外をスローすることはあっても、スタックオーバーフローを引き起こすことはない。一方、C/C++の動的メモリ確保はそのような言語と比べてオーバーヘッドが大きいため、あらゆる配列をヒープに確保しようとするのは大きな速度損失を伴う。Microsoft Visual C++のランタイムライブラリでは、一定のしきい値を基準として、要求されるメモリサイズに応じてスタックとヒープを使い分ける_malloca()関数も用意されている[8]。
脚注
- ^ Storage-class specifiers - cppreference.com
- ^ Thread Stack Size - Win32 apps | Microsoft Learn
- ^ /F (Set Stack Size) | Microsoft Learn
- ^ /STACK (Stack allocations) | Microsoft Learn
- ^ 2.4 スタックとスタックサイズ - Oracle Solaris Studio 12.2: OpenMP API ユーザーガイド
- ^ Verifying app behavior on the Android runtime (ART) | App quality | Android Developers
- ^ Threading Programming Guide - Thread Management | Apple Developer Documentation Archive
- ^ _malloca | Microsoft Learn
関連項目
- Stack_Overflowのページへのリンク