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

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

新規登録して質問してみよう
ただいま回答率
85.48%
関数

関数(ファンクション・メソッド・サブルーチンとも呼ばれる)は、はプログラムのコードの一部であり、ある特定のタスクを処理するように設計されたものです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

3回答

15154閲覧

[C++]関数内で動的確保後 -> ヒープが壊れていることが原因です[VC++2010]

退会済みユーザー

退会済みユーザー

総合スコア0

関数

関数(ファンクション・メソッド・サブルーチンとも呼ばれる)は、はプログラムのコードの一部であり、ある特定のタスクを処理するように設計されたものです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2014/11/24 06:09

いつもすみません。データ構造のスタックを実際にプログラムしてみようということで、クラステンプレート形式でつくってみたのですがデバックを実行し、return 0のとこまで処理が進んだところ、「ヒープが壊れています」と怒られました。
いろいろと検査しグーグル先生に見てみたところ、push()ないで領域を2倍に拡張する際に利用するresize()に問題があるらしいことまではわかったのですが、ダブルdeleteはしていないし、newで確保した領域以外にアクセスしているようなコードも(見落としがあるかもしれませんが)ないですし、途方に暮れています。
コピーする最初の数行ですが、copy宣言時のサイズを10、m_usageTopを5にしたり、m_usageTopの変化を観察したりしてみましたが特に異常はありませんでした。

bool Stack<T>::resize(){
// 今持っている領域の内容を別に移す
T* copy = new T[m_usageTop];
// const unsigned int csize = m_usageTop + 1; // コンストラクタで初期化だとコンパイル時に決定してないので不定
for(unsigned int i = 0; i < m_usageTop; i++){
copy[i] = item[i];
}

// 領域再確保 try{ if(size <= 1) delete item; else delete[] item; item = nullptr; item = new T[2*size]; size = 2 * size; // bad_allocがthrowされるとここは動作しない }catch(std::bad_alloc){ std::cout << "std::bad_alloc" << std::endl; if(item == nullptr) item = new T[size]; else{ delete[] item; item = new T[size]; } if( m_usageTop <= 1) delete copy; else delete[] copy; copy = nullptr; return false; } // 移していた領域を確保先に移す for(unsigned int i = 0; i < size; i++){ if( i < m_usageTop) item[i] = copy[i]; else item[i] = 0; } if( m_usageTop <= 1) delete copy; else delete[] copy; copy = nullptr; return true;

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

領域外のアクセス以外で関係ありそうなコアダンプの原因で思いつくのは 2 つです。

  • サイズ 0 で領域確保 new T[0]
  • 配列用 で領域を確保(new T[n])して、 1 つだけ削除(delete)
    あるいはその逆(new Tdelete[])

コンストラクターの方を見てないので、よくわかりませんが、この 2 つが原因じゃないかと思います。
ちなみに NULL を delete してもエラーではないので、コアダンプはしません。

あと、要素が 1 個の時で場合分けされていますが、 要素が 1 個の配列 new T[1] は作れます。
それよりはサイズ 0 のスタックは作れた方が使い勝手がいいので、 0 と 1 以上で場合分けした方がわかりやすいコードになると思います。

投稿2014/11/25 10:00

yohshiy

総合スコア863

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2014/11/26 12:31

ありがとうございます。 もう解決してしまいましたが、お返事を。delete関連ですが、その部分についてのみ、サイズの場合分けをしている(サイズが1ならdelete、サイズが2以上=配列ならdelete[])ので要素の場合分けも合わせて問題ないかと思います。サイズ0の宣言ですが、絶対にsizeは1以上になるようにつくっているのでそこも大丈夫だと思います。 原因は実はclear()という別の関数にあったという落ちでした・・・。
guest

0

0じゃないや1以上

投稿2014/11/25 04:03

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

部分的にしか見ていませんが、気になるところとして、copy[i] = item[i];この処理は範囲外の領域にアクセスする可能性がある気がします。

投稿2014/11/24 06:21

TaMaMhyu

総合スコア1356

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

TaMaMhyu

2014/11/24 06:26

と思いましたがそういうわけでもなさそうですね…
TaMaMhyu

2014/11/24 06:36

質問に書かれている範囲だとよくわかりませんが、sizeが0である場合はないでしょうか? sizeが0だと変な動きを思想ですが…
退会済みユーザー

退会済みユーザー

2014/11/25 04:01

ありがとうございます。Stack.sizeは一応コンストラクタで0以上になるように、というようにはしています。そのあとStack.sizeだけを直接変更するコードはないですが、いわれてみるともうちょっとassertで確実に見ていった方が良いとおもいました。今から確かめてみます
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問