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

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

ただいまの
回答率

89.12%

メモリ獲得失敗に対応できていることのテスト、どうしてますか?

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 4,676

Chironian

C++総合1位

近代的なOSの多くは仮想記憶をサポートしています。
仮想記憶領域としてHDDを使っている場合、空きメモリ無しになるのはHDDがフルになる時の筈なので、ヒープ・メモリの獲得に失敗することはまずないように思います。

以前、Windows 7上のプログラムでメモリ不足のテストをしようとしたのですが、newでどんどんメモリ確保し物理メモリの空きがなくなっているにも関わらず、動作が極端に遅くなるだけで例外が飛んで来ることがありませんでした。仮想記憶が働いてメモリ獲得に失敗しなかったものと思います。
結局、その時はメモリ獲得失敗時のテストは断念しました。

メモリ獲得に失敗した場合にできることはプロセスを落とすくらいしかないとは思いますが、悪さをしないで落ちること、できればメモリ不足で落ちたことの記録が残ることの確認をできるものならしておきたいと感じます。
でも、その程度の確認しかできないと思うので、データベース系のような矛盾が生じるとかなりやばいようなソフトウェアでなければ、多量の工数をかけてまでテストする必要性を感じません。

皆さんはどのようにしてますか?


【追記】
解決済にしましたが、「皆さんはどのようにしてますか?」の部分についてはアンケートですので、よろしかったら他の方からも回答を頂けると幸いです。

ああ、「テストしてないよ」って公の場で発言するのは難しいかもしれないですね。
「メモリ獲得失敗に対応できていること」のテストの意味です。
このテストをしない場合でも、一般にメモリ獲得に失敗しないことはテストしていると思います。
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+2

スワップするのが困るならスワップしないようにシステムを設定すればいいような気がします。
あとは、試したことはないのですが、VirtualAllocで大量の仮想メモリ空間を予約してしまえば、スワップさせずにメモリ確保失敗させられると思います。確かLinuxにも似たようなシステムコールがあります。

多量の工数をかけてまでテストする必要性を感じません。 
デスクトップ向けならそうかもしれませんが、搭載メモリに制限のある組み込み系はやはりテストしないとまずい気がします。シビアなタイミングでのデバイス制御や応答性重視のために、そもそも「スワップさせない」というケースも多いですし。
その場合はメモリ確保に失敗したらどうするかというよりは、開発段階で「失敗させないようにメモリをやりくりする」ためにテストしながら調整するという感じになるかもしれませんね。

書き忘れました。
皆さんはどのようにしてますか? 
私は以前、かなりプアーな組み込み機器の開発に携わったことがあるのですが、あまりのメモリ搭載量の少なさで、malloc/free等の関数をフックしてメモリ確保量を完璧に把握できるようにしてメモリ使用量を調整したことがあります。

結果報告
軽く試してみました。
手元の環境では、仮想アドレス空間を140737460043776バイト予約してから、4980736バイトまで確保できたところで256KiB確保しようとしたらbad_allocがスローされました。

テスト環境:Windows 10 Pro 64bit 搭載メモリ16GB/VC++2015

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/11/22 00:40

    >newやmallocで確保するメモリはCランタイムライブラリが管理する領域であって、
    > OSが自身で使うための領域とは別管理なので、

    newやmallocはヒープがなくなったらOSからメモリを貰ってきますので、newやmallocがメモリ獲得できない時は、ユーザ・プログラムがOSからメモリを獲得できない状態です。

    Windows APIはユーザ・モードで動作する部分も少なくありませんし、ユーザ・プログラムとWindowsはメモリ・プールを共有していると思っていました。(ページング禁止メモリ等一部のメモリはカーネル専用と思いますが、極一部との認識です。)

    > それによって確保に失敗しないということが保証できればテストする必要はありませんから。

    ええ、私もそれが現実的な解と思います。

    キャンセル

  • 2015/11/22 10:14

    > ユーザ・プログラムとWindowsはメモリ・プールを共有していると思っていました。

    この辺は必ずしもそうではないと私は考えています。ファイルシステムのようなカーネルモードで動くAPIは当然ユーザー空間とは明確に分離されていますし、ユーザーモードで動くAPIも、多くの場合、初期化関数やDLLエントリーで自分で使う分の領域はあらかじめ確保しているはずです(私ならそのように実装します)。ですから、使えるアドレス空間は共有していますが、メモリプールは別管理(各コンポーネントが自前で管理)しているはずです。ソースが開示されていないので確実にそうだとは言い切れませんが。
    もちろん、内部で動的なメモリ確保を行うAPIではユーザープログラムがメモリを使いすぎることで失敗する可能性もありますが、そういう場合はだいたいリファレンスにその記述がありますね。

    >> OSが自身で使うための領域とは別管理なので、

    と書いた理由はそういうことです。

    キャンセル

  • 2015/11/22 12:30

    なるほど。
    まとめると、catsforepawさんはユーザ・メモリ不足状態でもWindows APIは動作すると考えており、メモリ不足対応処理時Windows APIは呼んでも良いとのお考えですね。
    でも、catsforepawさんも書かれているように、それは推測ですよね?
    もし、推測なら、その状況も作って少なくとも一度は動作することを確認しておく必要があると思います。
    極限状況でエラー・ログをファイルに書こうとして、フォルダをアクセスできなくなったりしたら、目も当てられません。

    なので、正直メモリ不足処理でログを残すのは通常のアプリでは現実的ではないと感じてます。仮想記憶環境下ではハードディスクもフルになっているので、ファイルへの追記さえ危ういですし。OSのログに期待です。

    せめて悪させずにプロセス終了することくらいなら、なんとかテストできないかなと思います。メモリ不足時、単にプロセス終了しかしてなければ、VirtualAllocを使ってのテストは有効と感じてます。

    キャンセル

+1

メモリ確保エラー時の判定をする箇所は一度は実際に動作させるべきです。
デバッガで操作して、動作を確認するようにしてます。
(自動テストで毎回テストをすることまではしていません。コード作成時に数回、手操作で確認する程度です)

参考情報:
- Linuxでメモリ枯渇をテストするには http://d.hatena.ne.jp/shouh/20140426/1398470438
...
デバッガで無理矢理通す
...

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/11/21 21:36 編集

    ご回答、ありがとうございます。
    実際に実施されているのですね。
    費用対効果の低いテストなので悩ましいです。コストを下げることができるとよいのですが...

    【追記】
    たぶん、newをオーバーロードしてn回目でbad_allocできるコードを作れればそこそこ良いテストができそうですね。

    キャンセル

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

  • ただいまの回答率 89.12%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る