static宣言について

このQ&Aのポイント
  • C言語とDXライブラリを使ってゲームを製作している中で、static宣言された変数を配列の要素に指定するとプログラムが強制終了してしまう問題が発生しています。
  • また、GetColor関数でもstatic宣言された変数に格納すると意図しない色が表示される問題も確認されています。
  • いくつかの試みを行った結果、別のcppファイルで値を+1する関数を作成し、それを使用することで問題を解決することができましたが、何故このような事が起きるのかがわかりません。
回答を見る
  • ベストアンサー

static宣言について

現在、c言語とDXライブラリを使ってゲームを製作しています。 http://okwave.jp/qa/q8270456.html 前回、このような質問をさせていただき、原因らしき箇所を突き止める所までいきました。 と言いますのも、配列の要素を指定する箇所(分かり辛かったらすいません。要素数ではありません)に、static宣言された変数を入れるとなぜかプログラムが強制終了されてしまうのです。 加えて、DXライブラリのGetColor関数にも返ってきた色をStatic宣言された変数に格納すると、何故か指定された色と違う色が出てしまうことが分かりました。 なんとか、その関数が終わる度に値を格納したかったので、色々試しました。 直接Static宣言されていない変数を間に噛ませてみたり、同じcpp内にわざわざ別の関数を用意して、そちらでStatic宣言し、値を返してみたり、と色々とやったのですが上手くいきませんでした。 ****************************************** int hairetu[20]; Static int z = 0; int x = z-1+1 hairetu[x] = zahyouX; (static宣言された変数zでhairetu[]の[]内を指定しようとするとダメ) (上記のように意味のない計算をさせてstatic宣言されていない変数を間にかませてもダメ) ****************************************** 結局の所、別のcppを用意して、ただ一つのStatic変数を+1していくだけの関数をくみ上げた所、上手くいったのですが・・・。何故このような事が起きるのでしょうか。 Static宣言された変数の決まりごと、もしくは、このような状態になってしまった原因など、見当がつきましたら教えていただけると有難いです。よろしくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.3

static 変数を破壊すると言うことですが、大抵の処理系では、static な変数はメモリ上にそのまま並んで(隙間はあるかもしれませんが)配置されます。 なので、わかりやすい例だと、 static int wk[20]; static int z; か、 static int z; static int wk[20]; と書いて、wk[20] = 10000; とかすると、wk[] で確保されているはずの領域をはみ出して、z を書き潰します。 (多分、後者の書き方が下記つぶされる可能性が高いかと思います) この場合、 static int z; というのが関数の中で定義されていると、関数の中だけのスコープを持ちますから、他の関数で、直接zを壊すことはできません。 しかし、他の関数で、static 変数が定義されていると、変数は(関数ごとではなくて)全部の関数の static 変数がまとまって配置されることがあります(そういう処理系が多いと思う) なので、ほかの関数で定義されている static な(多分、配列)変数への代入が間違って、zを壊したか、あるいは、ポインタ経由の代入で、ポインタが正しいところを指していなかったかだと思います。 なお、他の関数で定義されている変数が、たまたまzの隣にあって、それが悪さをしているということだとすると、リンクの順序や、他の関数の変数の順序を入れ替えるだけで、問題が解決したように見えることがあります。 なので、問題の関数がそのままでも、一見問題が出たり出なかったりもします。

mitara42k
質問者

お礼

配列は hairetu[20] = {0};として初期化していますので、おそらく問題はないはずなのです。20になった場合、if文で0に戻すようにしていますので。 でも、問題が出ていたのが配列の箇所なんですよね・・・。 >なので、ほかの関数で定義されている static な(多分、配列)変数への代入が間違って、zを壊したか、あるいは、ポインタ経由の代入で、ポインタが正しいところを指していなかったかだと思います。 >なお、他の関数で定義されている変数が、たまたまzの隣にあって、それが悪さをしているということだとすると、リンクの順序や、他の関数の変数の順序を入れ替えるだけで、問題が解決したように見えることがあります。 >なので、問題の関数がそのままでも、一見問題が出たり出なかったりもします。 この辺りが非常に怖いため、もう一度、他の関数含めて宣言を見直してみたいと思います。分かり易く書いていただきまして、ありがとうございました。

その他の回答 (3)

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.4

まあ static だと「値が保存されている」と思い込んじゃうからかえって問題を見つけにくいかもしれんのだけど.... 「色々試しました」という中で, その変数の値を出力しようとは思いませんでしたか?

mitara42k
質問者

お礼

そういえばしませんでした。 元々ポインタの方に問題あるとばかり思っていたので、異常があったら出力することを覚えた方が良さそうですね。 ありがとうございました

  • Wr5
  • ベストアンサー率53% (2177/4070)
回答No.2

>Static変数の値って、どんな時に壊れるんでしょう? 非staticな変数でもそうですが、ふつ~は勝手に内容が壊れることはありません。 # 人工衛星などで放射線等に晒されてメモリチップ内の値が変わる。とかいうのでなければ。 CPUは「指示された通り」に愚直に値を書き換えます。 そこにはプログラマの意図が割り込むスキはありません。 「書かれた通りのコード」に従って動作するだけです。 # 書かれたコードがプログラマの意図と違っていても…です。 まぁ、最近のCPUとOSだとメモリ領域の一部を保護したりとかしている事もありますが…。 # static変数を保護している。とかではないです。プロセスに割り当てていないメモリアドレスへのアクセスを禁止していたり、OSのコード部分を書き換えたり出来ないように…などです。 って事で、どこかで貴方のコードが破壊するように指示しているのでしょう。 ポインタの理解が怪しいようですのでその辺りで間違いがあるとか、 配列の添え字をミスして他のものが書き換えているか……そういったところかと。 掲示された例だと… hairetu[x] = zahyouX; でxを参照する前にxの値をどこかで書き換えているのでしょう。 グローバル変数にしていて、全く関係無いところで書き換えている。なんてのはよくあるミスです。 # 衝突しそうな単純な変数名にしていると探すのは大変でしょうねぇ……。 VisualStudioで特定の領域が書き換えられたらブレークする。とかできましたかね…。 http://dixq.net/forum/viewtopic.php?f=3&t=11327 static変数ならプログラム起動時にはアドレス確定しているハズですから、上記の方法が採れるんじゃないですかね。 # 使ったことありませんけど。

mitara42k
質問者

お礼

いえ、そもそもcppを跨ぐようなグローバル変数を使っていない・・・はず! です。でも、staticを入れたつもりで入れていない。なんてミスがありそうです。 >VisualStudioで特定の領域が書き換えられたらブレークする。>とかできましたかね…。 少し内容が難しそうですが、なんとか理解したいと思います。ありがとうございました。

  • wormhole
  • ベストアンサー率28% (1622/5659)
回答No.1

どこかの処理で、そのstatic変数を壊してるだけでは? そのstatic変数を使用する直前にでも、その値が想定するものかどうか確認するコードを書き加えて確認してみてはどうですか。

mitara42k
質問者

お礼

おそらく全く解決していませんが、何が何だか分からない内に動くようにはなりました。次からは値を確認することを癖にしたいと思います。 ありがとうございました。

mitara42k
質問者

補足

意味が分からないのですが、あ、回答の話ではなく。 昨日・一昨日あわせて10時間くらい悩んで何回もプログラムを再起させてできなかったのに、以前と同じコードにしたら今はあっさり動くんです・・・、なんで・・・。 Static変数の値って、どんな時に壊れるんでしょう?

関連するQ&A

  • static付き宣言の初期化

    static付きの宣言をした場合の変数の初期化について教えてください。(ANSI-C) int func(void) { static int si; static char sca[10]; static char *scp; /* 何らかの処理 */ return 0; } このように関数内でstatic付きで宣言したとき、変数はどのように初期化されますか? siは0、sca[0]からsca[9]までは'\0'、scpはNULLで初期化されますか? また、このようなstatic付きの宣言が関数の外にあった場合は、どのように初期化されますか?

  • 配列変数の宣言「その2」

    「その2」 「その1」でも述べましたが、配列変数の宣言の仕方は2種類あると思います。 (1)・・・ int hairetu[]; (2)・・・ int [] hairetu; この宣言をした後、init()メソッドを使いこの2つの配列変数の範囲(?)を指定したいと思います。 (1)の指定方法・・・ hairetu = new int[10]; (2)の指定方法・・・ hairetu[] = new int[10]; (2)を指定するときは(1)の指定方法が使えませんでした。これはなぜでしょうか? 逆に、(1)を指定するときには(1)は配列変数であるにもかかわらず、[] なしでも指定ができるのでしょうか? 知っていれば教えてください。

    • ベストアンサー
    • Java
  • 配列変数の宣言「その1」

    「その1」 僕の見たことのある配列変数の宣言の仕方は2種類あります。 (1)・・・ int hairetu[]; (2)・・・ int [] hairetu; 現在は配列変数であることが分かりやすいという点で (2)が推奨されているというようなことは本で読んだことがあります。 今まではどちらかというと(1)をよく使っていました。 そこで、みなさんのご意見を聞いて、 今後どちらを使うのか考えてみたいと思いました。 (1)の良い所や良くない所、(2)の良い所や良くない所などもあれば教えてほしいです。

    • ベストアンサー
    • Java
  • VBAでstatic変数を宣言するとトラブル

    フォームにクエリーを基にしたリストボックスがあり、クエリーの抽出条件には同じフォームのテキストボックスを指定しています。テキストボックスには規定値プロパティーで"*"を設定しています。 それで問題なく開くことが出来ていたのですが、必要があってフォームモジュールでStatic変数を宣言したところ、クエリーが機能せず、指定したテキストボックスのパラメーター入力ダイアログが表示されます。static変数の宣言を削除するとちゃんと動きます。public変数やモジュール変数を宣言してもおなじ現象が起きます。 原因はなんでしょうか。またどうすればstatic変数などを使うことが出来るのでしょうか? よろしくお願いします。

  • 無名ネームスペース中のstatic宣言について

    お世話になります。 以下のように無名ネームスペース内でstatic定数を宣言することに 何か問題はあるでしょうか? QACという静的コードチェックツールで 「無名ネームスペース中のstatic宣言」と 警告が出てしまいます。 test.h ----------------------- class Test{ void testFunc(); }; test.cpp ------------------------ namespace { static const int i = 3; } void Test::testFunc(){ std::cout << i << std::endl; }

  • 分割ファイルでstatic変数はどのようにすれば良いのでしょうか?

    1つのファイルでstatic変数を使っている場合は気にしていなかったのですが、分割ファイルにした場合、static変数はどのようにすれば各ファイルで利用できるのでしょうか? 通常のグローバル変数の場合はexternとすれば良かったのですが方法がかわりません。 ** test1.cpp static int a; ** test2.cpp ?????? (二重定義になる) あと1ファイルから分割ファイルにした場合に気をつけるべき点など詳しい方教えて下さい。

  • Java main関数内でStatic変数使えない

    JavaのStatic変数について質問です。 Main関数の中でStaticな変数を定義しようとしたところ、 final修飾子しか使えませんというエラー文言が出ます。 Main関数内でわざわざStatic変数を使用する必要はないのですが、 出来ないと言われると何故だろうと思ってしまいます。 どなたかご説明いただけないでしょうか? -------------------------------------------------------------------- class Test { public static void main(String[] args) { // 宣言時Staticは使えなく、finalでしか定義できないとエラーが出る Static int test_val = 10; // 表示 System.out.println(test_val); } }

    • ベストアンサー
    • Java
  • staticの動作について

    C++で趣味でゲームを作っているのですが、staticを使ったときのローカル変数の動作について質問があります。 いまいち、ローカル変数の動作が分かっていないのですが、大雑把には、関数が読み出される毎に空いてるメモリを探して、そこを確保する物だと思ってます。 で、staticを用いて宣言すると内容が保持されると言うことは、これは始めに一回だけメモリの確保をして、以降はそれを継続して使っているというものなのでしょうか? だとすると、staticをつかったローカル変数の方が、繰り返しメモリの確保が行われ無い分、処理が早いということでしょうか? いま、ゲーム内では、描画用の関数描画基準座標とサイズを受け渡して入るのですが、どうしても内部で描画終了点と開始点のクリップを計算する必要があり、そのためにどうしても計算した開始点、終了点を保持する変数が必要になっています。 しかし、描画関数はキャラの分と背景描画の分とパーティクルの描画の分と、ゲーム1ループないでも1000回近く(多いときは2000回ぐらい)呼び出されてます。 その度にメモりの確保をされるのはなんか気分が悪いなぁと思ってstaticを何となくつているのですが、実際の所staticを着けたら動作がはやくなるとかと言うことは無いのでしょうか? 宜しくおねがします。

  • ポインタの宣言

    ポインタを宣言するとメモリ上に、ポインタ変数を格納するための領域が確保されます。ポインタ=アドレスというのは大丈夫なのですが、 int *b のようにどうして、ポインタに型があるのでしょうか?単に変数のアドレスを表示するだけならば型はいらないと思うのですが。 またこのとき宣言された変数は *b ではなくて b であってますよね?

  • 関数内、ファイルのstatic変数

    関数内で、static変数を宣言した場合に、その値は保持されると 思いますが、その関数の外からポインタで見る場合にその値は 保証されるのでしょうか? (必ず同じメモリ上に配置されるのでしょうか?) また、関数とファイル内static変数においてスコープ以外に 取り扱いが変わったりするのでしょうか? (配置されるメモリ空間等) よろしくお願い致します。