配列の宣言について。

お久しぶりです。

今回は配列の宣言について。

 

例によって例のごとくノベルゲームの(ryを組んでた際にエラーが発生

.exe の 0x00ac4bc4 でハンドルされていない例外が発生しました: 0xC0000005: 場所 0xdadad240 に書き込み中にアクセス違反が発生しました。

エラー発生時に実行されていた関数がこちら

void setScript(Script* pScript, const char* str) {
    int i, start = 1, size;
    const char* pStr;
    for (i = 0; i < 3; ++i){
        // ","を探す
        pStr = strstr(&str[start], ",");
        if (pStr == NULL ) // ,がない場合、行末(改行)を探す
            pStr = strstr(&str[start], "\n");
        size = pStr - &str[start];
        char Buf[ ] = {0};
        switch(i){
            case 0:
                strncpy(Buf, &str[start-1], size+1);
                Buf[size+1] = '\0';
                pScript->Name = Buf;
                break;
            case 1:
                strncpy(Buf, &str[start-1], size+1);  // ここでエラー発生
                Buf[size+1] = '\0';
                pScript->Message = Buf;
                break;
            case 2:

                // キーワードに合わせて読み込む画像を変える

                strncpy(Buf, &str[start-1], size+1);

                Buf[size+1] = '\0';
                if(strcmp(Buf, "A"))
                    pScript->bgGraph = LoadGraph(FILENAME_A);
                else if(strcmp(Buf, "B"))
                    pScript->bgGraph = LoadGraph(FILENAME_B);
                else if(strcmp(Buf, "C"))
                    pScript->bgGraph = LoadGraph(FILENAME_C);
                else if(strcmp(Buf, "D"))
                    pScript->bgGraph = LoadGraph(FILENAME_D);
                break;
            default:
                break;
        }
        start = start + size + 2;
    }
}

 

pScriptは以下の通り

struct Script{

    char* Name,Message;

    int bgGraph;

}script;

Script *pScript = &script;

 

FILENAME_◯は画像ファイルのパス(文字列)で定義済。

 

 

switch文のcase 1:とcase 2:の違いなんて代入先だけじゃないか!!と思いつつ色々調べてみる。

 

すると、問題があったのは......

\ switch文の前のBufの宣言!! /

char Buf[ ] = {0};

素数の動的確保、こいつが穴だった。

 

素数を指定しなかった場合、配列の利用時に要素数が確定される。

→case 1:で確定される。==  case 2:以降では既に確定している。

 

文字列の長さがNameに代入したい値よりも、Messageに代入したい値の方が長かった場合、配列の最終要素(書き込み禁止!!)にはみ出た分の最初の文字を代入しようとし、エラーを吐いた、ということだったようだ。

 

動的確保は便利だけど長さが未定で何度も使い回す場合には最初っから多めに確保したほうが良さそう。

動的に再定義とかできたら無駄がなくていいんだろうけど、そこまでの知識は俺には無いからなぁ......(´-ω-`)

 

これもまた調べたいことに追加して今回も終了、かな。

PS.冬コミまで日が無くなってきて焦ってます。ダレカタスケテー

2014/11/22 Sat.