こちらでは、はじめて質問させていただきますACです。
C++については大体基本はわかってるぐらいの知識です。
DxLibを使用してゲームのひな形でも作ろうなと思い、C++でリストを使ってタスクシステムを実装したのですが、一部挙動が不明のところがあり、いくら考えても分からず気になって気になってしょうがないので、質問するしだいに至りました。
ここには全てを書きにくいいのでソースをアップしましたのでそちらを参照しながら見ていただけたらと思います。
アドレス:http://www1.axfc.net/uploader/He/so/163203
ダウンロード&解凍パス:sitsumonyo
既に実行できる状態のVC2008のプロジェクトです(DxLibのインクルードとリンクはそちらの方でお願いします)。
まず、タスクシステムについては、これはhttp://www.tnksoft.com/さんのサイトの
http://www.tnksoft.com/reading/classgam ... 01/011.php
を参考にしています(ほぼまんまですが・・・)。
タスクに関する全処理はMaster.cppに書かれています。
さて本題ですが、不明な点はOpening.cppにあります。
簡単にいえば使いたいときに AddTask(new クラス名()...) でタスクに追加して、いらなくなったら RemoveTask(インスタンス) で削除すればよいのですが、Opening.cpp内でRemoveTask(this)のようにしてタスクを消したところ、エラーが出てしまいました(色々試しましたがOpening.cpp内でなくてもエラーが起こるようです)。
リストの要素のerase時にエラーが出てるらしく、どうもイテレータによる参照が変な感じであることがわかったのですが、なぜおかしくなるのかがどうしてもわかりませんでした。
少々面倒な質問ですが、エラーのでる理由のわかる方は教えていただけたら幸いです。よろしくお願いします。
C++によるタスクシステムに関する質問(少々面倒です)
Re:C++によるタスクシステムに関する質問(少々面倒です)
削除後のイテレータを設定し直していないためです。
× TaskList.erase(iter);
○ iter = TaskList.erase(iter);
× TaskList.erase(iter);
○ iter = TaskList.erase(iter);
Re:C++によるタスクシステムに関する質問(少々面倒です)
恐らく、自分自身を RemoveTask したあとは既にインスタンスは delete されているので、その後の自分自身に対する処理はエラーになります。
対処は、自分自身が RemoveTask した後に直ぐに出るか、 removeTask をタスクループ外で呼び出すか、
タスクシステムの構造を変えるかのどれかになります。
対処は、自分自身が RemoveTask した後に直ぐに出るか、 removeTask をタスクループ外で呼び出すか、
タスクシステムの構造を変えるかのどれかになります。
Re:C++によるタスクシステムに関する質問(少々面倒です)
御津凪さんの言うとおりですね。
今回の場合COpening01::Execメソッド内の
++timer;
のところで開放済みのクラスのメンバにアクセスしているため
アクセス違反を起こしています。
今回の場合COpening01::Execメソッド内の
++timer;
のところで開放済みのクラスのメンバにアクセスしているため
アクセス違反を起こしています。
Re:C++によるタスクシステムに関する質問(少々面倒です)
御津凪さん、GPGAさん、ご解答ありがとうございます。
まさしくおっしゃる通りでした。
サンプルだしー、という感じで何気なく書いてしまったtimer++が原因でしたorz。
ひとまず解決です。
ありがとうございました。
でも、それならまたいくつか疑問に思う点がありまして、
1.なぜこのエラーはプログラム終了時に発生するのか(delete時には発生してないようですので)
2.アップした質問用プロジェクトは作製途中の元ソースのエラー探しの過程でできたものでもあるのですが、元のソースの方ではVC側からはxmemory(リスト関連のヘッダ?)というところの
の2点がよく分かりません。
2の方は元ソースの方はアップしてないので情報不足でしたらスルーしてくださって構いません。
もしよかったら回答のほうよろしくお願いします。
まさしくおっしゃる通りでした。
サンプルだしー、という感じで何気なく書いてしまったtimer++が原因でしたorz。
ひとまず解決です。
ありがとうございました。
でも、それならまたいくつか疑問に思う点がありまして、
1.なぜこのエラーはプログラム終了時に発生するのか(delete時には発生してないようですので)
2.アップした質問用プロジェクトは作製途中の元ソースのエラー探しの過程でできたものでもあるのですが、元のソースの方ではVC側からはxmemory(リスト関連のヘッダ?)というところの
void deallocate(pointer _Ptr, size_type) { // deallocate object at _Ptr, ignore size → ::operator delete(_Ptr); }でエラーが起きているといわれるのですが、これは何を意味しているのか
の2点がよく分かりません。
2の方は元ソースの方はアップしてないので情報不足でしたらスルーしてくださって構いません。
もしよかったら回答のほうよろしくお願いします。
Re:C++によるタスクシステムに関する質問(少々面倒です)
1.については、deleteの処理自体は正常に処理され、
その後deleteされたthisポインタを持った状態で関数から戻ってきているので、
deleteされたthisポインタを参照してしまうとアクセス違反エラーになります。
もしエラーにならなくても、終了時に何らかの形で(ヒープが壊れているとか)エラーを出します。
(後者が該当する原因かと)
2.は1.によるものだと思われます。
ちなみに、ヒープが壊れているというのは、確保した領域の前後(あるいは確保していた領域)に
書き込みが行われたことが原因となります。
その後deleteされたthisポインタを持った状態で関数から戻ってきているので、
deleteされたthisポインタを参照してしまうとアクセス違反エラーになります。
もしエラーにならなくても、終了時に何らかの形で(ヒープが壊れているとか)エラーを出します。
(後者が該当する原因かと)
2.は1.によるものだと思われます。
ちなみに、ヒープが壊れているというのは、確保した領域の前後(あるいは確保していた領域)に
書き込みが行われたことが原因となります。
Re:C++によるタスクシステムに関する質問(少々面倒です)
御津凪さん、丁寧なご回答ありがとうございます。
完全に納得いたしました。
これにて全て解決ということにさせていただきます。
本当に勉強になりました。
ご回答してくださった皆様ありがとうございました。
完全に納得いたしました。
これにて全て解決ということにさせていただきます。
本当に勉強になりました。
ご回答してくださった皆様ありがとうございました。