
多次元配列のメモリ解放についてです。
以下のような方法で多次元配列を確保した場合に、
---
char** ppMain;
ppMain = new char*[3];
for (int i = 0; i < 3; i++){
ppMain[i] = new char[20];
}
---
メモリ解放する場合、
---
for (int i = 0; i < 3; i++){
delete [] ppMain[i];
ppMain[i] = NULL;
}
delete [] ppMain;
ppMain = NULL;
---
で良いでしょうか?
おそらく、new/deleteの回数が同じであれば問題ないと思うのですが。
少し混乱してしまって、
delete [] ppMain[i]; によって
new char*[3]で確保したところも解放されており
delete [] ppMain; が必要なく危険な領域まで解放しようとしているということはないでしょうか?
ご専門、お詳しいかたコメント宜しくお願いします。
A 回答 (5件)
- 最新から表示
- 回答順に表示
No.5
- 回答日時:
> それを考えると以下の方法であっても、
> 例外が送出される場合があるのではないでしょうか?
> char (*pMain)[20] = new char[3][20];
例外が送出される可能性はあります。
しかし、上の場合では、メモリの割り付けに成功するか、例外が送出されてメモリがまったく割り付けられないかのどちらかですので、中途半端な割付けが行われてメモリリークすることがありません。
この回答への補足
ご回答ありがとうございます。
"中途半端な割付け"の意味をいろいろ調べていて、
連絡遅れてしまいました。
調べても全く違いが分からなかったのですが、
(1)の場合の中途半端な割付けというところをもし良ければ
少しコメントいただけないでしょうか?
■(1)
for (int i = 0; i < 3; i++){
ppMain[i] = new char[20];
}
■(2)
char (*pMain)[20] = new char[3][20];
jactaさんの回答では、
(2)の場合は、割付けに失敗すればNULLが返って来るので問題ない。
(1)の場合には割付けに失敗してもNULLが返ってこない(適当なアドレスが返ってきてしまうので例外チェックも必須)ということだと思いますが、
その違いは何でしょうか?
(1)と(2)の違いというと1次元配列、2次元配列の違いしか私には分からないのですが、
その違いでメモリ割り当て方法が大きく変わってくるのでしょうか?
No.4
- 回答日時:
> (1)の場所で例外が送出?
> というのはどういうことでしょうか?
メモリの割付けに失敗した場合、newはstd::bad_alloc例外を送出します。
その場合、既に割付け済みのメモリブロックは解放の機会を失いますので、メモリリークにつながります。
これの回避は面倒ですが...
char** ppMain;
ppMain = new char*[3];
std::fill_n(ppMain, 3, 0);
try{
for (int i = 0; i < 3; i++){
ppMain[i] = new char[20];
}
}
catch (std::bad_alloc&){
for (int i = 0; i < 3; i++){
delete[] ppMain[i];
}
delete[] ppMain;
}
のようにする必要があります。
これが面倒であれば、
char (*pMain)[20] = new char[3][20];
とすれば、簡単になります。
ただし、ポインタ配列ではないのでサイズは固定です。
更に簡単にするには、
std::vector<std::vector<char> > vMain(3, std::vector<char>(20, '\0'));
とでもすればよいでしょう。
これなら可変サイズにも対応できますし、明示的な解放が不要になります。
ご回答ありがとうございます。
new / deleteというものをよく知らず、
用語をググりながら内容理解しました。
メモリ不足なり、何らかの理由でメモリアロケートに失敗し、
例外が起こる可能性があり、チェックが必要ということですね。
それを考えると以下の方法であっても、
例外が送出される場合があるのではないでしょうか?
char (*pMain)[20] = new char[3][20];
着目点が間違っていますでしょうか?
No.3
- 回答日時:
結論としては、お示しのコードで問題ありません。
以下、ちょっと細かく解説します。
まず、「new char*[3];」は「多次元配列」ではなく「ポインタの配列」を確保していることに気をつけてください。
両者はメモリ上のデータ配置が全く異なります。
前者はある空間に char が3×20並んでいることになりますが、後者はアドレス値が三つ並んでいるにすぎません。
そして「new char[20];」の繰り返しで得られるポインタ群は連続している空間を指しているとは限らず、ましてや「new char*[3];」とは全く関係のない場所である可能性もありえます。
そう考えると、「delete [] ppMain[i];」の時点では各「new char[20];」で確保した部分を開放しており、「delete [] ppMain;」では「new char*[3];」で確保したところを開放していることが理解しやすいと思います。
ご回答ありがとうございます。
多次元配列だと、こんな感じのことですね。
char hairetu[][][];
失礼しました。
ポインタの配列のみを解放しているという感じが不安でした。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
CStringからchar*への型変換に...
-
文字列内の数字削除
-
エクセルのMID関数は、C言語では?
-
C言語のintとcharの違いってな...
-
csvファイルを構造体に格納した...
-
c言語でcsvファイルの処理で、...
-
char AA[]{"全角文字"};から"全...
-
[C] 構造体メンバーのカンマ区...
-
C言語について質問です
-
char** buffer (このような2...
-
c言語関数の(1)~(5)までの部分...
-
const char* s1とただのchar s1...
-
#include <stdio.h> #include <...
-
char*を初期化したいのですが
-
警告
-
C言語にて構造体のメンバがNULL...
-
Vectorでヒープエラーが出る
-
C# ポインタ アクセス違反
-
WM_CHAR or WM_KEYDOWN の「wPa...
-
int型の文字列について
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
CStringからchar*への型変換に...
-
char*を初期化したいのですが
-
C言語にて構造体のメンバがNULL...
-
C言語のintとcharの違いってな...
-
DWORDとcharの変換
-
C++17で、unsigned char * 配列...
-
char 文字列型 の表現範囲が-12...
-
new charとnew char[N]の違いは?
-
char型にint型の数値を代入する。
-
動的メモリの初期化方法について。
-
小数点入りの文字列をfloat型に...
-
文字型配列に格納した空白の切捨て
-
fstream型オブジェクトを関数の...
-
C++Builder 2009 テキスト...
-
文字列の途中から途中までを抽出
-
C言語の文字リテラル中の16進文...
-
エクセルのMID関数は、C言語では?
-
文字列のswap
-
void型へのポインタ
-
VC++ char[10]へのCString値の代入
おすすめ情報