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

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

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

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

C++

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

Q&A

2回答

13803閲覧

【C++】ヒープが破壊されます(>_<)

mash0120

総合スコア10

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

C++

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

0グッド

0クリップ

投稿2016/04/16 10:30

編集2016/04/16 11:54

C++初心者です。
ヒープ破壊のエラーに、かれこれ2週間ほど苦しめられております。
何かわかる方いましたら回答をお願いします...助けてください...(>_<)汗

【発生手順】
「CreateBuffer」というFunctionで、pA1~pA16のバッファを作成します。
そして、pA1~pA16が作られた状態で「DeleteBuffer」が呼ばれるとpA1~pA16をdeleteしていきます。
pA15~pA16辺りをdeleteするときに以下のエラーが発生します。(たいていはpA16でエラーが発生する)

Windows によって HogeHoge.exe でブレークポイントが発生しました。
ヒープが壊れていることが原因として考えられます。HogeHoge.exe または読み込まれた DLL にバグがあります。
あるいは、HogeHoge.exe がフォーカスを持っているときに、ユーザーが F12 キーを押したことが原因として考えられます。
可能であれば、出力ウィンドウに詳細な診断情報が表示されます。

「CreateBuffer」でpA1~pA16をnewした直後に「DeleteBuffer」を呼んでみても同様のエラーが発生するので、構造体の作り方が悪かったりするのかなと考えているところです。

説明が不足している点は聞いていただければと思います。
皆さんのお知恵をお貸しください。よろしくお願いします。

また、ソースですがお見せすることができない場所もありますので、これがソースのすべてではありません。限られた情報しか提示できませんがご協力お願いします(ToT)

以下、問題のソースです。

typedef struct AData{ BYTE *pA1; //A1ポインタ BYTE *pA2; //A2ポインタ BYTE *pA3; //A3ポインタ BYTE *pA4; //A4ポインタ BYTE *pA5; //A5ポインタ BYTE *pA6; //A6ポインタ BYTE *pA7; //A7ポインタ BYTE *pA8; //A8ポインタ BYTE *pA9; //A9ポインタ BYTE *pA10; //A10ポインタ BYTE *pA11; //A11ポインタ BYTE *pA12; //A12ポインタ BYTE *pA13; //A13ポインタ BYTE *pA14; //A14ポインタ BYTE *pA15; //A15ポインタ BYTE *pA16; //A16ポインタ }
void HogeHoge::CreateBuffer( Int32 bufferSize ) { this->DeleteBuffer(); this->data->pA1 = new BYTE[ bufferSize ]; this->data->pA2 = new BYTE[ bufferSize ]; this->data->pA3 = new BYTE[ bufferSize ]; this->data->pA4 = new BYTE[ bufferSize ]; this->data->pA5 = new BYTE[ bufferSize ]; this->data->pA6 = new BYTE[ bufferSize ]; this->data->pA7 = new BYTE[ bufferSize ]; this->data->pA8 = new BYTE[ bufferSize ]; this->data->pA9 = new BYTE[ bufferSize ]; this->data->pA10 = new BYTE[ bufferSize ]; this->data->pA11 = new BYTE[ bufferSize ]; this->data->pA12 = new BYTE[ bufferSize ]; this->data->pA13 = new BYTE[ bufferSize ]; this->data->pA14 = new BYTE[ bufferSize ]; this->data->pA15 = new BYTE[ bufferSize ]; this->data->pA16 = new BYTE[ bufferSize ]; this->DeleteBuffer(); //テスト用に追加 }
void HogeHoge::DeleteBuffer() { if( this->data->pA1 != NULL ) { delete[] this->data->pA1; this->data->pA1 = NULL; } if( this->data->pA2 != NULL ) { delete[] this->data->pA2; this->data->pA2 = NULL; } if( this->data->pA3 != NULL ) { delete[] this->data->pA3; this->data->pA3 = NULL; } if( this->data->pA4 != NULL ) { delete[] this->data->pA4; this->data->pA4 = NULL; } if( this->data->pA5 != NULL ) { delete[] this->data->pA5; this->data->pA5 = NULL; } if( this->data->pA6 != NULL ) { delete[] this->data->pA6; this->data->pA6 = NULL; } if( this->data->pA7 != NULL ) { delete[] this->data->pA7; this->data->pA7 = NULL; } if( this->data->pA8 != NULL ) { delete[] this->data->pA8; this->data->pA8 = NULL; } if( this->data->pA9 != NULL ) { delete[] this->data->pA9; this->data->pA9 = NULL; } if( this->data->pA10 != NULL ) { delete[] this->data->pA10; this->data->pA10 = NULL; } if( this->data->pA11 != NULL ) { delete[] this->data->pA11; this->data->pA11 = NULL; } if( this->data->pA12 != NULL ) { delete [] this->data->pA12; this->data->pA12 = NULL; } if( this->data->pA13 != NULL ) { delete [] this->data->pA13; this->data->pA13 = NULL; } if( this->data->pA14 != NULL ) { delete [] this->data->pA14; this->data->pA14 = NULL; } if( this->data->pA15 != NULL ) { delete [] this->data->pA15; this->data->pA15 = NULL; } if( this->data->pA16 != NULL ) { delete [] this->data->pA16; this->data->pA16 = NULL; } }

↓以下追加のソースです。

HogeHoge.h

public ref class HogeHoge // データ取得バッファ(アンマネージ)のラッパ { private: FUGA_AREA* data; // データ取得バッファ public: int BufferSize; // バッファのサイズ HogeHoge(void); // コンストラクタ ~HogeHoge(void); // デストラクタ !HogeHoge(void); // ファイナライザ FUGA_AREA* GetReference(); // データ取得バッファのポインタを取得する void CreateBuffer( Int32 bufferSize ); // バッファを作成 void DeleteBuffer(); // バッファを削除 public: /// /// プロパティ /// property String^ IdName // ID名(S1~S100,R1~R100,M1~M100)(Read Only) { String^ get() { std::string s( this->data->aIdName ); return Utility::ToUnicode( s ); } }; property UInt32 AMaxSize // データ最大数(AデータのMAX値)(Read Only) { UInt32 get(){ return this->data->nMax; } }; property UInt32 Count // データ個数(property) { UInt32 get(){ return this->data->nCnt; } void set( UInt32 value ){ this->data->nCnt = value; } }; property Int32 CountReference // データ個数のポインタ(Read Only) { Int32 get(){ return (int)( &(this->data->nCnt) ); } }; property UInt32 StartPosition // データ開始位置(Read Only) { UInt32 get(){ return this->data->nStp; } }; property UInt32 EndPosition // データ終了位置(Read Only) { UInt32 get(){ return this->data->nEnp; } }; property String^ DataType // データ型(Read Only) { String^ get() { std::string s( this->data->aDataType ); return Utility::ToUnicode( s ); } }; property Int32 DataLength // データ長(Read Only) { Int32 get(){ return this->data->nDataLength; } }; property Int32 Status // 状態(Read Only) { Int32 get(){ return this->data->nStatus; } }; property Int32 A1Reference //A1データのポインタ(Read Only) { Int32 get() { return (int)( &( this->data->pA1[0] ) ); } }; property Int32 A2Reference //A2データのポインタ(Read Only) { Int32 get() { return (int)( &( this->data->pA2[0] ) ); } }; property Int32 A3Reference //A3データのポインタ(Read Only) { Int32 get() { return (int)( &( this->data->pA3[0] ) ); } }; property Int32 A4Reference //A4データのポインタ(Read Only) { Int32 get() { return (int)( &( this->data->pA4[0] ) ); } }; property Int32 A5Reference //A5データのポインタ(Read Only) { Int32 get() { return (int)( &( this->data->pA5[0] ) ); } }; property Int32 A6Reference //A6データのポインタ(Read Only) { Int32 get() { return (int)( &( this->data->pA6[0] ) ); } }; property Int32 A7Reference //A7データのポインタ(Read Only) { Int32 get() { return (int)( &( this->data->pA7[0] ) ); } }; property Int32 A8Reference //A8データのポインタ(Read Only) { Int32 get() { return (int)( &( this->data->pA8[0] ) ); } }; property Int32 A9Reference //A9データのポインタ(Read Only) { Int32 get() { return (int)( &( this->data->pA9[0] ) ); } }; property Int32 A10Reference //A10データのポインタ(Read Only) { Int32 get() { return (int)( &( this->data->pA10[0] ) ); } }; property Int32 A11Reference //A11データのポインタ(Read Only) { Int32 get() { return (int)( &( this->data->pA11[0] ) ); } }; property Int32 A12Reference //A12データのポインタ(Read Only) { Int32 get() { return (int)( &( this->data->pA12[0] ) ); } }; property Int32 A13Reference //A13データのポインタ(Read Only) { Int32 get() { return (int)( &( this->data->pA13[0] ) ); } }; property Int32 A14Reference //A14データのポインタ(Read Only) { Int32 get() { return (int)( &( this->data->pA14[0] ) ); } }; property Int32 A15Reference //A15データのポインタ(Read Only) { Int32 get() { return (int)( &( this->data->pA15[0] ) ); } }; property Int32 A16Reference //A16データのポインタ(Read Only) { Int32 get() { return (int)( &( this->data->pA16[0] ) ); } }; }

HogeHoge.cpp

/// /// 機能 : コンストラクタ /// HogeHoge::HogeHoge(void) { this->data = new FUGA_AREA; memset( this->data, 0, sizeof( FUGA_AREA ) ); this->BufferSize = 0; strcpy_s( this->data->aIdName, sizeof(this->data->aIdName), "R1" ); } /// /// 機能 : デストラクタ /// HogeHoge::~HogeHoge(void) { this->!HogeHoge(); } /// /// 機能 : ファイナライザ /// HogeHoge::!HogeHoge() { this->DeleteBuffer(); if( this->data != NULL ) { delete this->data; this->data = NULL; } }

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

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

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

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

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

guest

回答2

0

CreateBufferメソッドで、最初にDeleteBufferメソッドを呼び出していますが、この時点でAData構造体の各メンバ変数はNULLに初期化されていますでしょうか。ちゃんと初期化されていないと不正なポインタに対してdeleteやdelete[]を実行することになり、ヒープを壊す可能性があります。

それと、deleteおよびdelete[]はnullの時は何もしないという仕様なので、if( this->data->pA1 != NULL )のような判定は不要です。
また、delete[]とNULLの代入の順番を間違えている箇所がいくつもあります。メモリリークを引き起こします。

投稿2016/04/16 10:43

catsforepaw

総合スコア5938

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

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

mash0120

2016/04/16 12:01

「deleteおよびdelete[]はnullの時は何もしないという仕様」なのですね。無駄な処理でしたか。。また追加でソースを載せました。他にもどこか問題がありそうな場所があればご教授ください。お願いします。
catsforepaw

2016/04/16 13:31

マネージコードでしたか。ポインタはInt32ではなく`IntPtr`でキャストしてください。 とりあえず、ヒープ破壊につながるような問題は特に見当たりません。HogeHogeクラスを使う側に問題があるような気がします。どのように使っているのか判りませんが、バッファーサイズを超えてデータを書き込んだりしていませんか?
guest

0

こんにちは。

HogeHogeクラスの定義がないとよく分かりませんので、できればそれも提示下さい。

ご提示のソースで分かる範囲で答えてみます。
まず、pA1~pA16を初期化されてますでしょうか? 初期化しないとpA1~pA16の値は不定になります。
次に、DeleteBuffer()のpA12 以降の処理がそれ以前と順序が異なってます。この辺は単純ミスでは?

最後に、CreateBuffer()の先頭でDeleteBuffer()を呼んでいるのはなぜでしょうか?
HogeHogeクラス定義でpA1~pA16を初期化されているのであれば、念のための処理ということでしょうか?


【追記】
aIdNameがADataに含まれていないようです。
これの定義を間違っているということはないでしょうか?
何かミスしているとstrcpy_s()でヒープ破壊の可能性は若干あります。

さて、ビルドしてやってみようとしたのですが、手間が掛かりそうなので諦めました。
C++/CLIを知らないので#includeするべきヘッダが分かりません。
ADataのtypedefも尻切れトンボになってます。
ビルドできて、かつ、エラーが再現する最小限のソース・コードにして頂けると、何かお手伝いできるかも知れません。(申し訳ないけど保証はできないですが...)

ところで、C++/CLIはマイクロフソト・オリジナルなC++ライク言語で、C++ではありません。
もし、特に必要があるというわけでないのならば、通常のC++を使った方が知っている人が多いのでフォローも受けやすいし、WEB情報も多いですよ。

投稿2016/04/16 10:43

編集2016/04/16 13:04
Chironian

総合スコア23272

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

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

catsforepaw

2016/04/16 10:44

被っちゃいましたね。
mash0120

2016/04/16 11:58 編集

構造体の初期化ができていないとそのような事が起きるのですね...また追加でソースを載せました。恐れ入りますが、どの辺に問題がありそうかご教授ください。お願いします(ToT)
Chironian

2016/04/16 12:25

C++/CLIだったのですね。CLIは殆ど知らないのでお役に立てないかもしれませんが、トライしてみます。ちょっとおまちを。
Chironian

2016/04/16 12:27

catsforepawさん。 しかも、今度は分まで。偶然って意外に身近に起こるものなんですね。
catsforepaw

2016/04/16 13:43

C++/CLIはC++にマネージ拡張を施したものですが、C++としての仕様はほぼC++そのものです。cstdio(stdio.h)をインクルードしてprintfすることもできますし、STLも使えます。
Chironian

2016/04/16 14:08 編集

マクロソフトのオリジナルな拡張がなされた言語ですね。 C++ライクというよりはC++上位互換な言語と言った方が妥当でした。 ただ、tomomi_321さんはC++では使えない機能をバリバリつかってます。分かって使っているのであれば良いのですが、C++初心者を名乗られてますし、C++と思っているとやばいかと思って少し強い表現を使いました。
catsforepaw

2016/04/16 14:29

意図して書いたのでしたか。早とちりしてすみません。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問