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

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

新規登録して質問してみよう
ただいま回答率
85.50%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Visual Studio

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

C++

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

Q&A

解決済

1回答

1830閲覧

C++でヒープが破壊されてしまう

sukara

総合スコア11

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Visual Studio

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

C++

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

0グッド

0クリップ

投稿2018/08/02 10:37

前提・実現したいこと

C++で配列を管理するクラスを作成しているのですが,メモリの管理がうまくいきません。
free()する時にエラーが発生してしまいます。

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

ハンドルされない例外が 0x00000000778EF262 (ntdll.dll) で発生しました(ArrClass.exe 内): 0xC0000374: ヒープは壊れています。 (パラメーター: 0x0000000077959430)。

該当のソースコード

main.cpp

c++

1// 2#include <stdio.h> 3#include "ArrayClass.h" 4int main() { 5 int i, j; 6 double data0[] = { 0.0,1.1,2.2,3.3,4.4,5.5,6.6,7.7,8.8,9.9 }; 7 ptrP<double> d1(10); 8 for (i = 0; i < 10; i++) { 9 d1.set(i, data0[i]); 10 } 11 ptrP<double> d2(8); 12 d2 = d1;//reallocしてコピー 13 for (int i = 0; i < 10; i++) { 14 printf_s("d2 [%d] = %f\n", i, d2.get(i)); 15 } 16 17 return 0; 18}

ArrayClass.h

C++

1// 2#pragma once 3#include <stdlib.h> //mallocなど 4enum eReturn { //Returnする数値 5 eReturn_Error = 0, 6 eReturn_Success, 7 eReturn_MallocError, 8 eReturn_ReallocError, 9 eReturn_MallocError_size0, 10}; 11/****************************************************************************************/ 12//void memAllocError();//mallocエラーの出力 13//void memAllocSizeError();//malloc時のサイズが0のとき出力 14//void memReallocError();//reallocエラーの出力 15//void memAcccessError();//メモリアクセスエラーの出力(配列の範囲外にアクセスしようとした時) 16/*****************************************************************************************/ 17template <typename TYPE> 18int cpyP (TYPE*& pTo, TYPE* pFrom, int sizeArr[1]);//配列のコピー 19 20/****************************************************************************************/ 21template <typename TYPE> 22int memAllocP (TYPE*& p , int sizeArr[1]); 23 24template <typename TYPE> 25int memReallocP (TYPE*& p , int sizeArrFr[1], int sizeArr[1]); 26 27/*******************************************************************************************/ 28template <typename TYPE> 29class ptrP {//1次元 30private: 31 32 void initialization(); //初期化 33 void cpyClass(const ptrP *o); //コピー 34public: 35 ptrP(); //コンストラクタ 36 ptrP(int size0); //コンストラクタ 37 ~ptrP(); //デストラクタ 38 ptrP(const ptrP &o); //コピーコンストラクタ (Ptr a=b;する時) 39 40 ptrP& operator=(const ptrP &o); //代入演算子 (Ptr a;a=b;する時) 41 bool flgMalloc; //mallocしたか 42 TYPE* v; //値 43 TYPE get(int i1); //値を返す 44 int set(int i1,TYPE value); //値を入れる 45 int sizeArr[1]; //確保した領域の個数 46 int memAlloc(int sizeArr0[1]); //メモリの確保 47 int memRealloc(int sizeArr0[1]); //メモリの拡張・縮小(データは引き継ぐ) 48 void memFree(); //メモリの開放 49}; 50 51 52#include "ArrayClass2.h" 53

ArrayClass2.h

C++

1// 2#ifndef pointer2_h//定義の重複回避 3#define pointer2_h 4 5#include "ArrayClass.h" 6/******************************************************************< 配列コピー > ******************************************************************/ 7template <typename TYPE> 8int cpyP(TYPE*& pTo, TYPE* pFrom, int sizeArr[1]) { //1次配列のコピー 9 int i1; 10 for (i1 = 0; i1 < sizeArr[0];i1++) { 11 pTo[i1] = pFrom[i1]; 12 } 13 return eReturn_Success; 14} 15/*********************************************************************< alloc > ******************************************************************/ 16template <typename TYPE> 17int memAllocP(TYPE*& p, int sizeArr[1]) { //1次元 18 if (1 > sizeArr[0]) { 19 //memAllocSizeError(); 20 return eReturn_MallocError_size0; 21 } 22 p = (TYPE*)malloc(sizeof(TYPE)*sizeArr[0]); 23 if (NULL == p) { 24 free(p); 25 //memAllocError(); 26 return eReturn_MallocError; 27 } 28 return eReturn_Success; 29} 30 31/********************************************************************< realloc > ******************************************************************/ 32 33template <typename TYPE> 34int memReallocP(TYPE*& p, int sizeArrFr[1], int sizeArr[1]) { //1次元 35 TYPE* p0; 36 if (eReturn_MallocError == memAllocP(p0, sizeArr))return eReturn_MallocError; 37 int size_min = sizeArrFr[0]; //サイズの小さいほうに合わせる 38 if (sizeArrFr[0] > sizeArr[0])size_min = sizeArr[0]; 39 for (int i = 0; i < size_min; i++) {//元の値をコピー 40 p0[i] = p[i]; 41 } 42 free(p); 43 p = p0; 44 return eReturn_Success; 45} 46 47/*********************************************************************< ptrP > ******************************************************************/ 48 49template <typename TYPE> 50ptrP<TYPE>::ptrP() { //コンストラクタ 51 initialization(); 52} 53template <typename TYPE> 54ptrP<TYPE>::ptrP(int size0) { //コンストラクタ 55 int sizeArr[1]; 56 sizeArr[0] = size0; 57 initialization(); 58 memAlloc(sizeArr); 59} 60template <typename TYPE> 61ptrP<TYPE>::ptrP(const ptrP &o) { //コピーコンストラクタ(doubleP a=b;する時に呼ばれる) 62 initialization(); 63 cpyClass(&o); 64} 65template <typename TYPE> 66ptrP<TYPE>& ptrP<TYPE>::operator=(const ptrP &o) { //代入演算子(doubleP a;a=b;する時に呼ばれる) 67 if (this == &o) return *this; //自己代入 68 cpyClass(&o); 69 return *this; 70} 71template <typename TYPE> 72void ptrP<TYPE>::cpyClass(const ptrP *o) { //クラスのコピー 73 int sizeArr0[1] = { o->sizeArr[0] }; 74 memRealloc(sizeArr0); 75 cpyP(v, o->v, sizeArr); 76} 77template <typename TYPE> 78ptrP<TYPE>::~ptrP() { //デストラクタ 79 memFree(); 80} 81template <typename TYPE> 82void ptrP<TYPE>::initialization() { //初期化 83 flgMalloc = false; 84} 85template <typename TYPE> 86int ptrP<TYPE>::memAlloc(int sizeArr0[1]) { //メモリ確保 87 int eResult; 88 if (flgMalloc)memFree(); //メモリ一旦解放 89 eResult=memAllocP(v, sizeArr0); //メモリの新規確保 90 if (eReturn_Success == eResult) { 91 flgMalloc = true; 92 sizeArr[0] = sizeArr0[0]; 93 } 94 return eResult; 95} 96template <typename TYPE> 97int ptrP<TYPE>::memRealloc(int sizeArr0[1]) { //メモリ拡張,縮小 98 int eResult; 99 if (flgMalloc) { //メモリ拡張,縮小 100 eResult=memReallocP(v, sizeArr0, sizeArr); 101 sizeArr[0] = sizeArr0[0]; 102 }else { //メモリの新規確保 103 eResult = memAlloc(sizeArr0); 104 } 105 return eResult; 106} 107template <typename TYPE> 108void ptrP<TYPE>::memFree() { //メモリの開放 109 if (flgMalloc) { 110 free(v); //ここでエラー// 111 flgMalloc = false; 112 } 113} 114template <typename TYPE> 115TYPE ptrP<TYPE>::get(int i1) { //値を返す 116 if (i1 < 0 || sizeArr[0] <= i1) { 117 //memAcccessError(); 118 return NULL; 119 } 120 return v[i1]; 121} 122template <typename TYPE> 123int ptrP<TYPE>::set(int i1, TYPE value) { //値を入れる 124 if (i1 < 0 || sizeArr[0] <= i1) { 125 //memAcccessError(); 126 return eReturn_Error; 127 } 128 v[i1] = value; 129 return eReturn_Success; 130} 131 132#endif 133

試したこと

/**< 配列コピー > **/の

pTo[i1] = pFrom[i1];

の部分をコメントアウトするとエラーが出なくなるので,
この部分で確保していない領域のメモリにアクセスし破壊されたのだと思います.
しかし,なぜメモリが確保できていないのかが分かりません。

また,d2の出力を見ると正しくコピーは出来ています。

よろしくお願い致します。

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

・Windows7 64bit/Windows10 64bit
・VisualStudioCommunity2017
・C++

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

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

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

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

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

guest

回答1

0

ベストアンサー

c++

1template <typename TYPE> 2int memReallocP(TYPE*& p, int sizeArrFr[1], int sizeArr[1])

sizeArrFrsizeArrは、どちらが変更前のサイズでどちらが変更後のサイズか、ちゃんと把握していますか?

mallocしているところにブレークポイントを置いてステップ実行すればすぐ判ることですが、d2 = d1;の処理で、d2の新しい領域をサイズ8で確保しています。結果的にコピー先のサイズが小さいのでバッファオーバーランを起こしています。

memReallocP内の処理では、新しい領域の確保でmemAllocP関数にsizeArrを渡していますが、ptrP<TYPE>::memRealloc関数の中からは、sizeArrFrに新しいサイズ、sizeArrに現在のサイズを渡しています。結果的に元のサイズのままです。

投稿2018/08/02 12:04

catsforepaw

総合スコア5938

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

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

sukara

2018/08/02 13:00

意図通りに動かすことができました ありがとうございました
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問