質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.79%

c++の学校の課題でfree();:invalid size Aborted(core dumped)の原因がわかりません。

解決済

回答 3

投稿

  • 評価
  • クリップ 0
  • VIEW 1,577

akaikesan

score 23

前提・実現したいこと

学校の課題の
エラーの原因を知りたい、エラーを解決したい

発生している問題・エラーメッセージ

free(): invalid size
                    Aborted (core dumped)

該当のソースコード

#include <curses.h>
#include <stdlib.h>

//ぷよの色を表すの列挙型
//NONEが無し,RED,BLUE,..が色を表す
enum puyocolor { NONE, RED, BLUE, GREEN, YELLOW };


//メモリ開放
class PuyoArray{
private:
    //盤面状態
    puyocolor *data;
    //盤面の行数,列数
    unsigned int data_line;
    unsigned int data_column;


    void Release()
    {
        if (data == NULL) {
            return;
        }
        delete[] data;
        data = NULL;
    }


public:
    PuyoArray(){
        //盤面状態
        puyocolor *data = NULL;
        //盤面の行数,列数
        unsigned int data_line = 0;
        unsigned int data_column = 0;


    }
    ~PuyoArray(){
        Release();
    }

    void ChangeSize(unsigned int line, unsigned int column)
    {
        Release();

        //新しいサイズでメモリ確保
        data = new puyocolor[line*column];

        data_line = line;
        data_column = column;
    }

    //盤面の行数を返す
    unsigned int GetLine()
    {
        return data_line;
    }

    //盤面の列数を返す
    unsigned int GetColumn()
    {
        return data_column;
    }

    //盤面の指定された位置の値を返す
    puyocolor GetValue(unsigned int y, unsigned int x)
    {
        if (y >= GetLine() || x >= GetColumn())
        {
            //引数の値が正しくない
            return NONE;
        }

        return data[y*GetColumn() + x];
    }

    //盤面の指定された位置に値を書き込む
    void SetValue(unsigned int y, unsigned int x, puyocolor value)
    {
        if (y >= GetLine() || x >= GetColumn())
        {
            //引数の値が正しくない
            return;
        }

        data[y*GetColumn() + x] = value;
    }

};



//盤面サイズ変更
class PuyoControl{
public:
//盤面に新しいぷよ生成
    void GeneratePuyo(PuyoArray &puyo)
    {
        init_pair(0, COLOR_WHITE, COLOR_BLACK);
        init_pair(1, COLOR_BLUE, COLOR_BLACK);
        init_pair(2, COLOR_GREEN, COLOR_BLACK);
        init_pair(3, COLOR_YELLOW, COLOR_BLACK);
        init_pair(4, COLOR_RED, COLOR_BLACK);



        puyo.SetValue(0, 5, static_cast<puyocolor>(rand() % 4 + 1));

        puyo.SetValue(0, 6, static_cast<puyocolor>(rand() % 4 + 1));
    }

    //ぷよの着地判定.着地判定があるとtrueを返す
    bool LandingPuyo(PuyoArray &puyo)
    {
        bool landed = false;

        for (int y = 0; y < puyo.GetLine(); y++)
        {
            for (int x = 0; x < puyo.GetColumn(); x++)
            {
                if (puyo.GetValue(y, x) != NONE && y == puyo.GetLine() - 1)
                {
                    landed = true;

                    //着地判定されたぷよを消す.本処理は必要に応じて変更する.
                    puyo.SetValue(y, x, NONE);
                }
            }
        }

        return landed;
    }

    //左移動
    void MoveLeft(PuyoArray &puyo)
    {
        //一時的格納場所メモリ確保
        puyocolor *puyo_temp = new puyocolor[puyo.GetLine()*puyo.GetColumn()];

        for (int i = 0; i < puyo.GetLine()*puyo.GetColumn(); i++)
        {
            puyo_temp[i] = NONE;
        }

        //1つ左の位置にpuyoactiveからpuyo_tempへとコピー
        for (int y = 0; y < puyo.GetLine(); y++)
        {
            for (int x = 0; x < puyo.GetColumn(); x++)
            {
                if (puyo.GetValue(y, x) == NONE) {
                    continue;
                }

                if (0 < x && puyo.GetValue(y, x - 1) == NONE)
                {
                    puyo_temp[y*puyo.GetColumn() + (x - 1)] = puyo.GetValue(y, x);
                    //コピー後に元位置のpuyoactiveのデータは消す
                    puyo.SetValue(y, x, NONE);
                }
                else
                {
                    puyo_temp[y*puyo.GetColumn() + x] = puyo.GetValue(y, x);
                }
            }
        }

        //puyo_tempからpuyoactiveへコピー
        for (int y = 0; y < puyo.GetLine(); y++)
        {
            for (int x = 0; x < puyo.GetColumn(); x++)
            {
                puyo.SetValue(y, x, puyo_temp[y*puyo.GetColumn() + x]);
            }
        }

        //一時的格納場所メモリ解放
        delete[] puyo_temp;
    }

    //右移動
    void MoveRight(PuyoArray &puyo)
    {
        //一時的格納場所メモリ確保
        puyocolor *puyo_temp = new puyocolor[puyo.GetLine()*puyo.GetColumn()];

        for (int i = 0; i < puyo.GetLine()*puyo.GetColumn(); i++)
        {
            puyo_temp[i] = NONE;
        }

        //1つ右の位置にpuyoactiveからpuyo_tempへとコピー
        for (int y = 0; y < puyo.GetLine(); y++)
        {
            for (int x = puyo.GetColumn() - 1; x >= 0; x--)
            {
                if (puyo.GetValue(y, x) == NONE) {
                    continue;
                }

                if (x < puyo.GetColumn() - 1 && puyo.GetValue(y, x + 1) == NONE)
                {
                    puyo_temp[y*puyo.GetColumn() + (x + 1)] = puyo.GetValue(y, x);
                    //コピー後に元位置のpuyoactiveのデータは消す
                    puyo.SetValue(y, x, NONE);
                }
                else
                {
                    puyo_temp[y*puyo.GetColumn() + x] = puyo.GetValue(y, x);
                }
            }
        }

        //puyo_tempからpuyoactiveへコピー
        for (int y = 0; y <puyo.GetLine(); y++)
        {
            for (int x = 0; x <puyo.GetColumn(); x++)
            {
                puyo.SetValue(y, x, puyo_temp[y*puyo.GetColumn() + x]);
            }
        }

        //一時的格納場所メモリ解放
        delete[] puyo_temp;
    }

    //下移動
    void MoveDown(PuyoArray &puyo)
    {
        //一時的格納場所メモリ確保
        puyocolor *puyo_temp = new puyocolor[puyo.GetLine()*puyo.GetColumn()];

        for (int i = 0; i < puyo.GetLine()*puyo.GetColumn(); i++)
        {
            puyo_temp[i] = NONE;
        }

        //1つ下の位置にpuyoactiveからpuyo_tempへとコピー
        for (int y = puyo.GetLine() - 1; y >= 0; y--)
        {
            for (int x = 0; x < puyo.GetColumn(); x++)
            {
                if (puyo.GetValue(y, x) == NONE) {
                    continue;
                }

                if (y < puyo.GetLine() - 1 && puyo.GetValue(y + 1, x) == NONE)
                {
                    puyo_temp[(y + 1)*puyo.GetColumn() + x] = puyo.GetValue(y, x);
                    //コピー後に元位置のpuyoactiveのデータは消す
                    puyo.SetValue(y, x, NONE);
                }
                else
                {
                    puyo_temp[y*puyo.GetColumn() + x] = puyo.GetValue(y, x);
                }
            }
        }

        //puyo_tempからpuyoactiveへコピー
        for (int y = 0; y < puyo.GetLine(); y++)
        {
            for (int x = 0; x < puyo.GetColumn(); x++)
            {
                puyo.SetValue(y, x, puyo_temp[y*puyo.GetColumn() + x]);
            }
        }

        //一時的格納場所メモリ解放
        delete[] puyo_temp;
    }


    //表示
};
void Display(PuyoArray &puyo)
{
    //落下中ぷよ表示
    for (int y = 0; y < puyo.GetLine(); y++)
    {
        for (int x = 0; x < puyo.GetColumn(); x++)
        {
            switch (puyo.GetValue(y, x))
            {
                case NONE:
                attrset(COLOR_PAIR(0));
                mvaddch(y, x, '.');
                break;
                case RED:
                attrset(COLOR_PAIR(4));
                mvaddch(y, x, 'R');
                break;
                case BLUE:
                attrset(COLOR_PAIR(1));
                mvaddch(y, x, 'B');
                break;
                case GREEN:
                attrset(COLOR_PAIR(2));
                mvaddch(y, x, 'G');
                break;
                case YELLOW:
                attrset(COLOR_PAIR(3));
                mvaddch(y, x, 'Y');
                break;
                default:
                mvaddch(y, x, '?');
                break;
            }

        }
    }


    //情報表示
    int count = 0;
    for (int y = 0; y < puyo.GetLine(); y++)
    {
        for (int x = 0; x < puyo.GetColumn(); x++)
        {
            if (puyo.GetValue(y, x) != NONE)
            {
                count++;
            }
        }
    }

    char msg[256];
    sprintf(msg, "Field: %d x %d, Puyo number: %03d", puyo.GetLine(), puyo.GetColumn(), count);
    mvaddstr(2, COLS - 35, msg);

    refresh();
}

//ここから実行される
int main(int argc, char **argv){
    PuyoArray puyo;
    PuyoControl ctrl;
    //画面の初期化
    initscr();
    //カラー属性を扱うための初期化
    start_color();

    //キーを押しても画面に表示しない
    noecho();
    //キー入力を即座に受け付ける
    cbreak();

    curs_set(0);
    //キー入力受付方法指定
    keypad(stdscr, TRUE);

    //キー入力非ブロッキングモード
    timeout(0);


    //初期化処理
    puyo.ChangeSize(LINES/2, COLS/2);    //フィールドは画面サイズの縦横1/2にする
    ctrl.GeneratePuyo(puyo);    //最初のぷよ生成

    int delay = 0;
    int waitCount = 20000;

    int puyostate = 0;


    //メイン処理ループ
    while (1)
    {
        //キー入力受付
        int ch;
        ch = getch();

        //Qの入力で終了
        if (ch == 'Q')
        {
            break;
        }

        //入力キーごとの処理
        switch (ch)
        {
        case KEY_LEFT:
            ctrl.MoveLeft(puyo);
            break;
        case KEY_RIGHT:
            ctrl.MoveRight(puyo);
            break;
        case 'z':
            //ぷよ回転処理
            break;
        default:
            break;
        }


        //処理速度調整のためのif文
        if (delay%waitCount == 0){
            //ぷよ下に移動
            ctrl.MoveDown(puyo);

            //ぷよ着地判定
            if (ctrl.LandingPuyo(puyo))
            {
                //着地していたら新しいぷよ生成
                ctrl.GeneratePuyo(puyo);
            }
        }
        delay++;

        //表示
        Display(puyo);
    }


    //画面をリセット
    endwin();

    return 0;
}

補足情報(FW/ツールのバージョンなど)

どこがおかしいのか全く検討がつきません。どうか助けてください

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

+3

public:
    PuyoArray(){
        //盤面状態
        puyocolor *data = NULL;
        //盤面の行数,列数
        unsigned int data_line = 0;
        unsigned int data_column = 0;
    }

コンストラクタ内でメンバ変数の初期化ではなくローカル変数を定義しています。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/05/12 13:38

    puyocolor *data;
    //盤面の行数,列数
    unsigned int data_line;
    unsigned int data_column;

    public:
    PuyoArray() {
    data = NULL;
    //盤面の行数,列数
    data_line = 0;
    data_column = 0;
    }
    このようにしたらうまく行きました。
    コンストラクタ内ではローカル変数は定義できないという解釈でよろしいのでしょうか?

    キャンセル

  • 2019/05/12 13:56

    ローカル変数へ代入したところで、同名のメンバ変数へは代入できないということです。
    メンバ変数と同名のローカル変数を宣言した事で、メンバ変数が隠れてしまうのです。

    キャンセル

  • 2019/05/12 14:01

    理解できたと思います。
    ありがとうございました。

    キャンセル

+1

Release(部分だと思うけど)デバッグしたら?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/05/12 13:23

    やってみたらReleaseで止まりました

    お答えありがとうございます

    キャンセル

  • 2019/05/12 18:18

    スマホで回答したんで言葉足らずだった^^;
    通常メモリ解放でエラーになるのは、開放時のアドレスが違っている&アドレスがNULLではない場合です。
    なので、そのへんを手掛かりにブレークを貼って開放するアドレスを確認すればたいてい解決します。
    ・・・間違っていたら、それが何処で設定された値なのかを確認しましょうd^^

    キャンセル

  • 2019/05/12 20:07

    参考にします

    ありがとうございます!

    キャンセル

+1

PuyoArray を new して delete するだけのコードを書いて動かしてみてください。
おそらく同じエラーが出ます。
Release() では delete[] 後に data に NULL を代入していますから(蛇足ですが data == NULL の検査は不要です)、それ以外に data に NULL でもなく new したものでもないデータが入るケースがあるはずです。

ところで、課題はこのプログラムを書いて出すことですか? 単にこのプログラムのデバッグ(プログラムは与えられたもの)ですか? 後者だとヒントを出しすぎたかもしれません。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/05/12 14:01

    やってみました。
    考える機会を下さり感謝します。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.79%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る