安全に大きなサイズのメモリを確保するには?

解決


浅葱  2001-12-22 20:49:05  No: 50040  IP: [192.*.*.*]

はじめまして、浅葱と申します。
いきなり質問で失礼だとは思いますが、
数日前に友人から「大きなサイズのメモリを動的に確保すると危険なんだよ」と
言われたんですが、いったい何がどう危険なのかよくわかりません。

char *p = new char[300000];

こんなプログラムを組んでみたんですが、正常に動いてるみたいです。
いったい何が危険なんでしょうか?
安全に確保する方法があるのでしょうか?

編集 削除
アポルテ  2001-12-22 21:39:32  No: 50041  IP: [192.*.*.*]

>いったい何がどう危険なのかよくわかりません。

危険というよりメモリが確保できない場合があると処理が出来ないからでしょう。

>安全に確保する方法

大きなメモリを確保する場合は4096バイトごとに確保していくのが通常らしいです。(その方がメモリが確保しやすい&処理が高速らしいです。)

※私自身その4096という値の意味は知りませんが・・・

編集 削除
浅葱  2001-12-23 00:30:44  No: 50042  IP: [192.*.*.*]

そうなんですか。
4096バイトごとに確保していくといいんですね〜
アポルテさん、どうもありがとうございました。

編集 削除
KF  2002-01-07 21:51:21  No: 50043  IP: [192.*.*.*]

・new で確保してdeleteを忘れる.
確保するメモリのサイズには関係ないですが,メモリを動的に確保すると
メモリを開放するのを忘れる問題が出てきます.最悪はプログラムが
動かなくなったり,OSが不安定になる可能性もあります.

・メモリが確保できない場合は判断できますから適切に処理すれば問題ないです
しかし,メモリが確保できないからといってその先にアプリケーションが
どのように動作するべきかが非常に難しいです.

・4096バイト単位に確保するのが通常というのは聞いたことがないです.
あるコンパイラに特有の現象でしょうか?
newの実装方法次第ではありえない話ではないとおもいますが.

編集 削除
ひろゆき  2002-02-15 13:04:45  No: 50044  IP: [192.*.*.*]

newの使い方というか
書き方なのですが
僕がよく使っている方法です。
TRY
{
  char *p = new char[300000];
}
CATCH(CMemoryException, e)
{
  e->delete();


}

編集 削除
ひろゆき  2002-02-15 13:13:25  No: 50045  IP: [192.*.*.*]

ごめんなさい
まちがって、送信を押してしまったので
もう一度かきなおします。
TRY
{
  /*ここでメモリを確保する*/
  char *p = new char[300000];
}
CATCH(CMemoryException, e)
{
  /*メモリの確保を失敗したときにくるそれ以外はここにはこない*/
  e->Delete();
  p = NULL;
}  
END_CATCH
という感じでメモリを確保しています。
KFさんがいっているように
delete [](char*)p;
のように、確保したメモリを開放してやらないと
いけません。もししなかったらリソースを食いつぶして
しまいますので、気をつけましょう。

編集 削除
YuO  2002-05-03 15:40:13  No: 50046  IP: [192.*.*.*]

今更ですが……。

まず,
TRY - CATCHではなく,try - catchのC++例外を使った方がいいです。
現在,MFCもC++の例外を利用しています。

それでもって,ISO/IEC 14882:1998では,newに失敗するとstd::bad_alloc例外を発生させます。
VC++の場合,VC++ 6.0まではNULLを返す時代錯誤の仕様ですが,
VC++.NETでは,C++の標準ライブラリを使うとstd::bad_alllocを投げるようになります。
なので,普通のメモリ確保は
char *p;
try {
    p = new char [300000];
} catch (std::bad_alloc &) {
    // エラー処理
}
となります。もっとも,
std::vector<char> p;
try {
    p.resize(300000);
} catch (std::bad_alloc &) {
    // エラー処理
}
の方が勧められますが。


あと,4Kバイトごとなのは,80386以降のCPUの制限です。
80386以降のCPUでは,メモリを4Kバイトのページを単位として割り付けています。
VirtualAllocなどのAPIでは,その制限をもろに受けます。

編集 削除
ryotaro331  URL  2002-05-05 12:14:05  No: 50047  IP: [192.*.*.*]

僕が使っている方法では、
VirtualAlloc関数でメモリを取得しています。
もう解決してしまったので口の出しようも無いかもしれませんが・・・。

編集 削除