- ベストアンサー
static宣言について
- C言語とDXライブラリを使ってゲームを製作している中で、static宣言された変数を配列の要素に指定するとプログラムが強制終了してしまう問題が発生しています。
- また、GetColor関数でもstatic宣言された変数に格納すると意図しない色が表示される問題も確認されています。
- いくつかの試みを行った結果、別のcppファイルで値を+1する関数を作成し、それを使用することで問題を解決することができましたが、何故このような事が起きるのかがわかりません。
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
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の隣にあって、それが悪さをしているということだとすると、リンクの順序や、他の関数の変数の順序を入れ替えるだけで、問題が解決したように見えることがあります。 なので、問題の関数がそのままでも、一見問題が出たり出なかったりもします。
その他の回答 (3)
- Tacosan
- ベストアンサー率23% (3656/15482)
まあ static だと「値が保存されている」と思い込んじゃうからかえって問題を見つけにくいかもしれんのだけど.... 「色々試しました」という中で, その変数の値を出力しようとは思いませんでしたか?
お礼
そういえばしませんでした。 元々ポインタの方に問題あるとばかり思っていたので、異常があったら出力することを覚えた方が良さそうですね。 ありがとうございました
- Wr5
- ベストアンサー率53% (2173/4061)
>Static変数の値って、どんな時に壊れるんでしょう? 非staticな変数でもそうですが、ふつ~は勝手に内容が壊れることはありません。 # 人工衛星などで放射線等に晒されてメモリチップ内の値が変わる。とかいうのでなければ。 CPUは「指示された通り」に愚直に値を書き換えます。 そこにはプログラマの意図が割り込むスキはありません。 「書かれた通りのコード」に従って動作するだけです。 # 書かれたコードがプログラマの意図と違っていても…です。 まぁ、最近のCPUとOSだとメモリ領域の一部を保護したりとかしている事もありますが…。 # static変数を保護している。とかではないです。プロセスに割り当てていないメモリアドレスへのアクセスを禁止していたり、OSのコード部分を書き換えたり出来ないように…などです。 って事で、どこかで貴方のコードが破壊するように指示しているのでしょう。 ポインタの理解が怪しいようですのでその辺りで間違いがあるとか、 配列の添え字をミスして他のものが書き換えているか……そういったところかと。 掲示された例だと… hairetu[x] = zahyouX; でxを参照する前にxの値をどこかで書き換えているのでしょう。 グローバル変数にしていて、全く関係無いところで書き換えている。なんてのはよくあるミスです。 # 衝突しそうな単純な変数名にしていると探すのは大変でしょうねぇ……。 VisualStudioで特定の領域が書き換えられたらブレークする。とかできましたかね…。 http://dixq.net/forum/viewtopic.php?f=3&t=11327 static変数ならプログラム起動時にはアドレス確定しているハズですから、上記の方法が採れるんじゃないですかね。 # 使ったことありませんけど。
お礼
いえ、そもそもcppを跨ぐようなグローバル変数を使っていない・・・はず! です。でも、staticを入れたつもりで入れていない。なんてミスがありそうです。 >VisualStudioで特定の領域が書き換えられたらブレークする。>とかできましたかね…。 少し内容が難しそうですが、なんとか理解したいと思います。ありがとうございました。
- wormhole
- ベストアンサー率28% (1626/5665)
どこかの処理で、そのstatic変数を壊してるだけでは? そのstatic変数を使用する直前にでも、その値が想定するものかどうか確認するコードを書き加えて確認してみてはどうですか。
お礼
おそらく全く解決していませんが、何が何だか分からない内に動くようにはなりました。次からは値を確認することを癖にしたいと思います。 ありがとうございました。
補足
意味が分からないのですが、あ、回答の話ではなく。 昨日・一昨日あわせて10時間くらい悩んで何回もプログラムを再起させてできなかったのに、以前と同じコードにしたら今はあっさり動くんです・・・、なんで・・・。 Static変数の値って、どんな時に壊れるんでしょう?
お礼
配列は hairetu[20] = {0};として初期化していますので、おそらく問題はないはずなのです。20になった場合、if文で0に戻すようにしていますので。 でも、問題が出ていたのが配列の箇所なんですよね・・・。 >なので、ほかの関数で定義されている static な(多分、配列)変数への代入が間違って、zを壊したか、あるいは、ポインタ経由の代入で、ポインタが正しいところを指していなかったかだと思います。 >なお、他の関数で定義されている変数が、たまたまzの隣にあって、それが悪さをしているということだとすると、リンクの順序や、他の関数の変数の順序を入れ替えるだけで、問題が解決したように見えることがあります。 >なので、問題の関数がそのままでも、一見問題が出たり出なかったりもします。 この辺りが非常に怖いため、もう一度、他の関数含めて宣言を見直してみたいと思います。分かり易く書いていただきまして、ありがとうございました。