スタックオーバーフローをなくす

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
Nekonami
記事: 21
登録日時: 11年前

スタックオーバーフローをなくす

#1

投稿記事 by Nekonami » 11年前

こんばんは。早速ですが質問を。
現在、DXライブラリで簡単なキーコンフィグのようなものを作っています(十字キーの操作をWASDに変える、というもの。以下「コントロールサイドの設定」)。
そこで実際に動作確認をしようとコントロールサイドの設定画面に行こうとすると、スタックオーバーフローが発生します。
内容を確認すると、ReturnKeyCode(int Getinput)で止まってしまうようです。
オーバーフローを起こしているローカル変数として表示されているのがGetinput(仮引数)です。

知識不足で解決法がわかりません。
どのようにオーバーフローを解決したらいいでしょうか?
この場合、グローバル変数を使って設定したほうがいいんですかね?

以下に必要と思われるコードを書いておきます。
Config.cpp

コード:

#include "DxLib.h"
// ↓  キーの入力状態を返す
#include "Keyboard.h" 
#include "ReturnKeyCode.h"

// ここから実際にはヘッダファイル(Config.h)に書いています
typedef enum{
    CMenu_CtrlSide,   // コントロールサイドの設定
    CMenu_Back,   // 戻る

    CMenu_Num,   // 本項目の数
} CMenu ;// 「設定」での選択状態

typedef enum{
    CLeftSide,   // 左側(WASD)
    CRightSide,   // 右側(矢印)
} CSelectSide;  // 「コントロールサイド」の選択状態
// ここまで


// 更新
static int NowSelect = CMenu_CtrlSide;    // 「設定」での現在の選択状態(初期は「コントロールサイドの設定」選択中)
static int NowSelect_Side = CRightSide;   // 「コントロールサイド設定」での現在の選択状態(初期は「右側(矢印)」選択中)


// 「設定」の更新
void Config_Update(){ 

    if(Keyboard_Get(ReturnKeyCode(Down))==1){   // 上キーが押されていたら
        NowSelect = (NowSelect+1)%CMenu_Num;    // 選択状態を一つ下げる
    }
    if(Keyboard_Get(ReturnKeyCode(Up))==1){   // 下キーが押されていたら
        NowSelect = (NowSelect+(CMenu_Num-1))%CMenu_Num;   // 選択状態を一つ上げる
    }
    if(Keyboard_Get(ReturnKeyCode(Enter))==1){   // 決定キーが押されたら
        switch(NowSelect){   // 現在選択中の状態によって処理を分岐
        case CMenu_CtrlSide:   // 「コントロールサイドの設定」選択中なら
	    CtrlSide_Update();   // シーンをコントロールサイドの設定画面に変更
            break;
        case CMenu_Back;   //「戻る」選択中なら
            Menu_Update();   // トップメニューに戻る
        }
    }
    if(Keyboard_Get(ReturnKeyCode(Back))==1){    // 戻るキーが押されていたら
        if(NowSelect == Back){   // 「戻る」選択中なら
            Menu_Update;   // シーンをメニューに変更
	}else{   // それ以外なら
            NowSelect = Back;    // 選択状態を「戻る」にする
        }
    }
}

// 「コントロールサイドの設定」の更新
void CtrlSide_Update(){ 
    if(Keyboard_Get(ReturnKeyCode(Left))==1){    // 左キーが押されていたら
        NowSelect_Side = CLeftSide;    // 左側(WASD)へ
    }
    if(Keyboard_Get(ReturnKeyCode(Right))==1){     // 右キーが押されていたら
        NowSelect_Side = CRightSide;      // 右側(矢印)へ
    }
    if(Keyboard_Get(ReturnKeyCode(Enter))==1){    // 決定キーが押されたら
        switch(NowSelect_Side){      // 現在選択中の状態によって処理を分岐
        case CLeftSide:      // 左側(WASD)なら
            ReturnKeyCode_Data(CLeftSide);      // ReturnKeyCode→SaveCtrlSide に設定を保存
            break;
        case CRightSide:      // 右側(矢印)なら
            ReturnKeyCode_Data(CRightSide);    // 上に同じ
        }
        Config_Update();    // 「設定」トップに戻る
    }
}

コード:

#pragma once

void ReturnKeyCode_Data(int GetCtrlSide);   // 「コントロールサイドの設定」で選んだコントロールサイドを保存する関数
int ReturnKeyCode(int Getinput);   // どの方向への入力かを引数に、対応するキーコードを設定されたコントロールサイドに応じて返す関数

typedef enum{
    Up,   // 上へ動かす操作
    Down,   // 下へ動かす操作
    Left,   // 左へ動かす操作
    Right,   // 右へ動かす操作
    Enter,   // 決定する操作
    Back   // 戻る操作
} input ; // どの入力のときの操作か

typedef enum{
    LeftSide,   // 左側(WASD)
    RightSide   // 右側(矢印)
} CtrlSide ; // 保存されたコントロールサイド
ReturnKeyCode.cpp

コード:

#include "DxLib.h"
#include "ReturnKeyCode.h"

static CtrlSide SaveCtrlSide = RightSide;   // コントロールサイドデータ格納用変数

// 「コントロールサイドの設定」で選んだコントロールサイドを保存する関数
void ReturnKeyCode_Data(int GetCtrlSide){
	if(GetCtrlSide == LeftSide){
		SaveCtrlSide = LeftSide;   // 「左側(WASD)」で保存
	}else{
		SaveCtrlSide = RightSide;   // 「右側(矢印)」で保存
	}
}

// どの入力のときかを引数に、対応するキーコードを設定されたコントロールサイドに応じて返す関数
int ReturnKeyCode(int Getinput){   
    if(SaveCtrlSide = LeftSide){  // 左側(WASD)のとき
        switch(Getinput){
        case Up:
            return KEY_INPUT_W;
            break;
        case Down:
            return KEY_INPUT_S;
            break;
        case Left:
            return KEY_INPUT_A;
            break;
        case Right:
            return KEY_INPUT_D;
            break;
        case Enter:
            return KEY_INPUT_LSHIFT;
            break;
        case Back: 
            return KEY_INPUT_LCONTROL;
	}
    }else{                          // 右側(矢印)のとき
        switch(Getinput){
        case Up:
            return KEY_INPUT_UP;
            break;
        case Down:
            return KEY_INPUT_DOWN;
            break;
        case Left:
            return KEY_INPUT_LEFT;
            break;
        case Right:
            return KEY_INPUT_RIGHT;
            break;
        case Enter:
            return KEY_INPUT_RSHIFT;
            break;
	case Back:
            return KEY_INPUT_RCONTROL;
        }
    }
}

Nekonami
記事: 21
登録日時: 11年前

Re: スタックオーバーフローをなくす

#2

投稿記事 by Nekonami » 11年前

追記:2番目のコードはReturnKeyCode.hです。

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: スタックオーバーフローをなくす

#3

投稿記事 by みけCAT » 11年前

スタックオーバーフローにつながるかはわかりませんが、
Config.cppの46行目

コード:

            Menu_Update;   // シーンをメニューに変更
ReturnKeyCode.cppの17行目

コード:

    if(SaveCtrlSide = LeftSide){  // 左側(WASD)のとき
の記述が不自然だと思いました。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: スタックオーバーフローをなくす

#4

投稿記事 by みけCAT » 11年前

Config.cppの、
Config_Update関数の38行目でCtrlSide_Update関数を呼び、
CtrlSide_Update関数の69行目でConfig_Update関数を呼んでいます。
しかも、Keyboard_Get(ReturnKeyCode(Enter))==1 && NowSelect==CMenu_CtrlSideを満たす状況なら
どちらも呼ぶ操作が行われるので、無限再帰になり、スタックオーバーフローになるのだと思います。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

Poco
記事: 161
登録日時: 14年前

Re: スタックオーバーフローをなくす

#5

投稿記事 by Poco » 11年前

スタックトレースはどうなっていますか?
Config_Update()とCtrlSide_Update()で無限に循環呼び出ししていませんか?

Nekonami
記事: 21
登録日時: 11年前

Re: スタックオーバーフローをなくす

#6

投稿記事 by Nekonami » 11年前

みけCAT さんが書きました:スタックオーバーフローにつながるかはわかりませんが、
Config.cppの46行目

コード:

            Menu_Update;   // シーンをメニューに変更
ReturnKeyCode.cppの17行目

コード:

    if(SaveCtrlSide = LeftSide){  // 左側(WASD)のとき
の記述が不自然だと思いました。
すこしわかりやすいように置き換えたときに間違えてしまったようです。
Config.cppの方は()が抜けていて、ReturnKeyCodeの方は論理演算子になっていませんでしたね。すみません。
みけCAT さんが書きました:Config.cppの、
Config_Update関数の38行目でCtrlSide_Update関数を呼び、
CtrlSide_Update関数の69行目でConfig_Update関数を呼んでいます。
しかも、Keyboard_Get(ReturnKeyCode(Enter))==1 && NowSelect==CMenu_CtrlSideを満たす状況なら
どちらも呼ぶ操作が行われるので、無限再帰になり、スタックオーバーフローになるのだと思います。
Poco さんが書きました:スタックトレースはどうなっていますか?
Config_Update()とCtrlSide_Update()で無限に循環呼び出ししていませんか?
あ・・・、気づきませんでした(汗
今日はもう遅いので、明日直してみようと思います。その後、改めて報告させていただきます。
ありがとうございました!

Nekonami
記事: 21
登録日時: 11年前

Re: スタックオーバーフローをなくす

#7

投稿記事 by Nekonami » 11年前

無事、解決しました!
原因はおっしゃる通り無限再帰でした。

ありがとうございました。

閉鎖

“C言語何でも質問掲示板” へ戻る