
初めて投稿させて頂きます。よろしくお願い致します。
現在、以下のような、2次元配列による動的なメモリの確保を意図して、コードをC/C++にて記述しています。
(コンパイラはMINGW32のg++ 3.4.5)
//mallocによるメモリ動的確保
data = (char **)malloc(num * sizeof(char*));
for(i=0; i<rowNum; i++){
data[i] = (char *)malloc(sizeof(char)*256);
}
//newによるメモリ動的確保
data = new char*[rowNum];
for(i=0; i<rowNum; i++){
data[i] = new char;
}
C++で書くのならば、
「mallocによるメモリ確保は辞め、newによるメモリ確保をしなさい」
という指摘が、書籍でもwebでもありましたので、
両方書き、両者を比べているのですが、理由がイマイチ分かりません。
10万行ほどのテキストデータで実験させてみたのですが、
mallocによる記述の方が、動作が数秒速いようなのです。
それで、new やmalloc で実際何をやっているのか、コードを見ようと思ったのですが、
newでは、
void* operator new(std::size_t) throw (std::bad_alloc);
void* operator new[](std::size_t) throw (std::bad_alloc);
void* operator new(std::size_t, const std::nothrow_t&) throw();
void* operator new[](std::size_t, const std::nothrow_t&) throw();
inline void* operator new(std::size_t, void* __p) throw() { return __p; }
inline void* operator new[](std::size_t, void* __p) throw() { return __p; }
というnewファイルの記述で行き詰まり、
malloc は malloc_allocator.hというファイルで行き詰りました。
以上を踏まえて、
1)そもそも、上記のメモリ動的確保記述はスマートな書き方なのか
2)実際に、newやmallocは、どういった手法でメモリ領域を確保しているのか
以上の2点について、ご教授下さい。よろしくお願い致します。
No.1ベストアンサー
- 回答日時:
まあ, operator new[] は operator delete[] のための管理情報を追加しなきゃならないのでどうしても malloc より遅くなる (少なくとも「速くなることだけはない」) んですけどね....
どうしても速度が欲しいなら malloc, お手軽を求めるなら std::vector を使うのが普通かな. ああ, 今どき 3.4.5 もどうかと思うので 4.3.3 なり 4.4.2 にするってのも考えるべきかと.
vectorで同様の処理を書いていたこともあったのですが、処理が重たくなり過ぎてしまったので、今はやっていません。
コード残しておけば良かったですが。。。どうやって書いてたかな。
MINGW32の標準は3.4.5で、4.x以降は開発版だとどこかで読んでいたので、3.4.5で開発していました。
4.xも検討してみます。
ご回答ありがとうございました。
No.9
- 回答日時:
> ごめんなさい、理解できません。
> arrayの要素数は静的に決まるかと。
私自身、少し混乱があったようです。
何を考えていたかというと...
配列を動的に割り付けたい動機というのは、サイズを可変にしたいか、記憶域期間の問題をクリアしたいか、どのどちらかのケースが多いと思います。
そこで、後者の場合であれば、
array<array<char, 256>, 10>* data = new array<array<char, 256>, 10>;
で済むのではないかと考えていました。
ただ、最初の話の流れでは、
vector<vector<char> > data;
とすることを(私自身)想定していましたので、一貫性を失っていますね。
もちろん、vectorを使った場合でも、記憶域期間の問題をクリアするには、
vector<vector<char> >* data = new vector<vector<char> >;
とすることになるのでしょうが。
実は記憶域期間の問題も抱えていて、別の形で質問させて頂こうと思っています。
STL等が十分に使える環境では、積極的にvectorを使ったほうが良さそうですね。
コメント頂いたキーワードから、知識の幅が広がりました。みなさん、ご回答ありがとうございました。
No.5
- 回答日時:
freeとdeleteを間違うようなプログラマは、(もっと紛らわしい)deleteとdelete[]を確実に使い分けられるとは思えません。
理想をいえば、そんなプログラマを使わないのが一番ですが、そうもいかないのであれば、配列形式のnewは全廃したほうがよいでしょう。
代わりはstd::vectorが最有力ですが、TR1が使える環境であれば、std::tr1::arrayでもよいと思います。std::vectorやstd::dequeを使う場合、push_backやinsert後に反復子が無効になるので、フールプルーフを考えると、std::tr1::arrayのほうがよいかもしれません。
プログラムは専門ではないのですが、freeとdeleteはきちんと使い分けています。
配列のときは、delete [] x; として開放しています。
恥ずかしながら、TR1の存在は知りませんでした。
vectorやdequeについても、少し検索してみましたが、とてもデータを扱いやすそうですね。
勉強になります。ありがとうございます。
No.4
- 回答日時:
> 「mallocによるメモリ確保は辞め、newによるメモリ確保をしなさい」
> という指摘が、書籍でもwebでもありましたので、
> 両方書き、両者を比べているのですが、理由がイマイチ分かりません。
newで確保したメモリはfree()で解放してはいけない
malloc()で確保したメモリはdeleteで解放してはいけない
という制約があります。
このため、1つのプロジェクトの中で、何の方針もなく
mallocによるメモリ確保とnewによるメモリ確保が入り乱れていると
後で解放する時にfreeすべきかdeleteすべきかを間違える可能性があり、
バグのもとになるとされています。
このことから、どちらかに統一すべきであり、
統一するなら、言語レベルでサポートされていて高機能である
newで統一すべきということが一般論として言われています。
(参考)
http://ja.wikipedia.org/wiki/Malloc#C.2B.2B.E3.8 …
No.3
- 回答日時:
newはmallocには無い機能があります。
例えばインスタンスをnewで生成する場合には、
引数付のコンストラクタを呼び出せます。
Hoge *h = new Hoge(1);
他にはnewは失敗した場合、例外を投げることができます。
new[]は他の回答者さんの仰る通りvectorを使う方がお手軽ですが、
STLを使いたくない等の理由がある場合は、new[]を普通に使います。
newにはそんな使い方もできたのですね。
これは知りませんでした。
malloc単体では例外を投げることが出来ないのも納得です。
STLは出来れば避けたいので、newでやってみようと思います。
ご回答、ありがとうございました!
No.2
- 回答日時:
GCCの場合、operator newはmallocを用いて実装されています。
mallocに失敗した場合にstd::set_new_handlerで登録した関数を呼び出し、(通常)例外を送出する処理を行うことになるため、どうしてもmallocより遅くなります。C++ではmallocを使ってはいけないのではなく、非C互換型に対してmallocを使ってはならないと考えたほうがよいでしょう。ただし、正しく使い分けられないのであれば、newに統一したほうが無難なことは確かです。
あと、配列形式のnewも、どうしてもそれを使わなければならない理由がない限りは避けたほうがよいでしょう。普通はstd::vectorを使います。bool型のようにstd::vectorが適切でない場合には、std::dequeを使うとよいでしょう。
MinGWのバージョンに関しては、現状の最新版は4.4.0ですが、-finput-charsetだったか-fexec-charsetだったかが正しく動作しなかったように記憶しています。これでは日本語がまともに使えないので、古いバージョンを使ったほうがましでしょう。
自分でコンパイルし直す手間を惜しまないなら、それもよいとは思いますが...
gccでは、newの中でもmallocを用いているんですね。
例外処理などで、安全性を高めるためにnewが実装されていると。
なるほど。
std::vectorだと、扱うデータが大きく処理速度が落ち過ぎるようなので、敬遠しています。std::dequeについては知りませんでしたので、勉強させて頂きます。
3.4.5でも、-finput-charsetや-fexec-charsetはきちんと動作してくれませんでした。今はその都度、エスケープしています。
逆に言えば、4.4.0にアップグレードしても、不安要素はそのくらいということですか・・・なら、アップグレードしてしまったほうがいいですね^^;
ご回答ありがとうございました!
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# c言語の問題です 課題1 (二分探索木とセット) 大きさ size の配列 array を考える。す 2 2023/01/10 21:08
- C言語・C++・C# const char** p;のとき、free(p)でC4090エラーとなるのはなぜですか 3 2023/03/31 16:28
- C言語・C++・C# C#テキストボックスの文字を配列にいれてその後表示する 4 2022/07/17 04:47
- C言語・C++・C# leetcode 155 minstack 1 2022/05/07 16:43
- Java java 入力 3 4 3 出力 ABC DEFG HIJ このようなプログラムの書き方を教えてくだ 2 2022/07/15 14:18
- C言語・C++・C# C++プログラミングコードにポリモーフィズムを取り入れ方を教えてください。 2 2023/06/09 11:17
- C言語・C++・C# 宣言する関数の形が決まっている状態で、 str1とstr2の文字列をこの順に引っ付けてstrに保存し 2 2022/05/30 18:21
- C言語・C++・C# C# で、あるフォルダー内にあるすべてのテキストファイルを別のフォルダーにコピーする。 4 2022/11/21 13:23
- Java javaでのプログラム(配列)について質問です. 2 2022/10/14 22:27
- C言語・C++・C# TCP/IP通信時のサーバーからの受信 2 2022/11/23 09:11
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
ビットをローテートするプログ...
-
newしないオブジェクトについて
-
プログラムが途中で強制終了し...
-
DLLで同じメモリ領域を参照する...
-
allocってなんですか?
-
メモリマップドファイルを可変...
-
C言語 mallocとfreeについて
-
メモリ解放について
-
callocの処理速度
-
C++で、メンバもヒープに確保さ...
-
HEAP に関すること
-
mallocについて
-
写真のc言語の問題がa以外わか...
-
CreateFileMapping について
-
JVMヒープサイズ設定について
-
配列の添え字の最大数とは?
-
DLLのマルチスレッドの動作につ...
-
関数から配列を返すには?
-
C言語 配列の長さの上限
-
配列の問題
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
c言語のポインタへの文字列入力...
-
allocってなんですか?
-
newしないオブジェクトについて
-
malloc呼び出し時のセグメンテ...
-
入れ子になった構造体について
-
ヒープメモリの解放について
-
ビットをローテートするプログ...
-
C++で、メンバもヒープに確保さ...
-
void*型のデータサイズ
-
Win32APIでのメモリ管理について
-
配列の添え字の最大数とは?
-
C++のnewで確保したメモリーの...
-
プログラムが途中で強制終了し...
-
C言語 mallocとfreeについて
-
win32APIのHeapAlloc()の使い方...
-
LoadLibraryでAccess Violation...
-
グローバル変数のサイズ
-
MFCのCStringについて
-
メモリ不足になってしまう。
-
ヒープの実際の限界値は?
おすすめ情報