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

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

新規登録して質問してみよう
ただいま回答率
85.48%
ソフトウェアテスト

ソフトウェアテストは、プログラムを実行し、要求通りに正しく動作が行えているかどうか確認する作業です。プログラム中のバグをできる限り多く発見することを目標として行われます。

Q&A

解決済

2回答

8395閲覧

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

Chironian

総合スコア23272

ソフトウェアテスト

ソフトウェアテストは、プログラムを実行し、要求通りに正しく動作が行えているかどうか確認する作業です。プログラム中のバグをできる限り多く発見することを目標として行われます。

0グッド

1クリップ

投稿2015/11/21 08:57

編集2015/11/21 17:07

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

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

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

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


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

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

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

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

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

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

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

guest

回答2

0

ベストアンサー

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

多量の工数をかけてまでテストする必要性を感じません。

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

書き忘れました。

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

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

結果報告

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

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

投稿2015/11/21 10:03

編集2015/11/21 12:40
catsforepaw

総合スコア5938

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

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

Chironian

2015/11/21 11:09

回答、ありがとうございます。 > VirtualAllocで大量の仮想メモリ空間を予約してしまえば なるほど。[2^64-実使用サイズ]バイトのメモリ空間を予約すればメモリ空間が足りないのでメモリ獲得失敗できるということですね!! メモリではなくメモリ空間を使いきるのか~。それは思いつきませんでした。 でも、うまいことできます? MMUの特性も考慮する必要がありそうで意外に苦労しそうな予感もします。 恐らく、catsforepawさん自身はメモリ獲得失敗しないことのテストを行ったのですね? 逆に言えば、メモリ獲得に失敗した時に不具合が起きないか?のテストは行っていないように読み取りました。その通りでしょうか?
catsforepaw

2015/11/21 11:33

> その通りでしょうか? YesでもありNoでもある、ですね。 メモリ確保失敗時のコードは必ず入れます。ログに出すようにもします。そして、テストコードを組み込んで、何らかの条件でわざとエラーになるような仕組みで、その失敗処理が正しく動くかどうかのテストも必ずします(もちろんリリースビルドでは無効化で)。 ただ、製造工程におけるテストが、回答に書いたケース以外では大抵「○○時間連続で動かして使用メモリが増え続けないこと」という具合なので、「実際にメモリ確保に失敗する」までテストしたことはありません。
catsforepaw

2015/11/21 12:20

> うまいことできます?  うまくいきました。回答の方に結果を追記しておきました。
Chironian

2015/11/21 12:33

うわっ、確認までして頂きありがとうございます。 最後に確認された環境はWindowsですか? Linuxですか? また、そのバージョンも教えて頂けると幸いです。
catsforepaw

2015/11/21 12:36

すみません。テスト環境書き忘れました。 Windows 10 Pro 64bit版、VC++2015です。
Chironian

2015/11/21 12:50

ありがとうございます。 これで低い工数でテストする可能性が見えてきました。 C++なら失敗処理自体はcatchすれば現実的な費用対効果でできそうですね。 全ての箇所でのbad_allocとなると厳しいですが、newを置き換えてできそうな気もしてきました。 皆さんも実施しているのであれば、私も頑張らねば。
Chironian

2015/11/21 13:04

あ! すいません、もう一点。 > その失敗処理が正しく動くかどうかのテストも必ずします メモリを獲得できない環境で正しく動くことまでテストされてます? 意外に難しいですこれ。 でも、メモリだけならVirtualAlloc使って環境つくれそうですね。 仮想メモリ環境ですとログ・ファイル書き込みさえできない可能性もありますので、そこまではテスト無理?
catsforepaw

2015/11/21 13:29

そこまではやったことないですね。ほとんどの場合アプリの仕様には動作環境も含まれていまして(最低動作環境:メモリ○GBとか)、それを下回る状況は想定しない(=テストしない)ですから。 > 仮想メモリ環境ですとログ・ファイル書き込みさえできない可能性もありますので、そこまではテスト無理? メモリが確保できない時点でシステムを正しく動作させることは期待できないので、なかなか難しいですよね。 メモリ(ヒープ領域)を消費しないログシステムを考えるしかないでしょうね。とりあえず、プログラム開始時にあらかじめ必要なメモリを確保して、メッセージは固定長のバッファでやりくりして、ファイルI/Oはシステムコール(Win32API)直叩きという感じでしょうか。
Chironian

2015/11/21 14:29

ですよね。メモリを獲得できない環境で、使っているWin32APIが正常動作することの確認も必要ですし動作しなかった時、代替案も実装しないといけないし。マジ大変です。 でも、そこまでしないと折角テストしても実際の環境とかなり異なる状態でのテストしかできていないからあまり意味ないし。 仮想記憶環境で起きる可能性がまずないことを考えると、費用対効果的にできることはやはり限られそうですね。
catsforepaw

2015/11/21 14:48

> メモリを獲得できない環境で、使っているWin32APIが正常動作することの確認も必要ですし newやmallocで確保するメモリはCランタイムライブラリが管理する領域であって、OSが自身で使うための領域とは別管理なので、new/mallocが失敗したからといってWin32APIが動かなくなることはないですよ。まぁ、絶対ないとは言い切れませんが、そういう状況を作り出すのは難しいと思います。
catsforepaw

2015/11/21 14:57

結局のところ「何を作るのか」でエラー対策は変わってきますし、例えばサーバーシステムや組み込み機器のように24時間365日稼働を前提とするなら、メモリ確保に失敗するほど「無制限にメモリを消費し続けない」ように作ることが最重要課題ですね。それによって確保に失敗しないということが保証できればテストする必要はありませんから。
Chironian

2015/11/21 15:40

>newやmallocで確保するメモリはCランタイムライブラリが管理する領域であって、 > OSが自身で使うための領域とは別管理なので、 newやmallocはヒープがなくなったらOSからメモリを貰ってきますので、newやmallocがメモリ獲得できない時は、ユーザ・プログラムがOSからメモリを獲得できない状態です。 Windows APIはユーザ・モードで動作する部分も少なくありませんし、ユーザ・プログラムとWindowsはメモリ・プールを共有していると思っていました。(ページング禁止メモリ等一部のメモリはカーネル専用と思いますが、極一部との認識です。) > それによって確保に失敗しないということが保証できればテストする必要はありませんから。 ええ、私もそれが現実的な解と思います。
catsforepaw

2015/11/22 01:14

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

2015/11/22 03:30

なるほど。 まとめると、catsforepawさんはユーザ・メモリ不足状態でもWindows APIは動作すると考えており、メモリ不足対応処理時Windows APIは呼んでも良いとのお考えですね。 でも、catsforepawさんも書かれているように、それは推測ですよね? もし、推測なら、その状況も作って少なくとも一度は動作することを確認しておく必要があると思います。 極限状況でエラー・ログをファイルに書こうとして、フォルダをアクセスできなくなったりしたら、目も当てられません。 なので、正直メモリ不足処理でログを残すのは通常のアプリでは現実的ではないと感じてます。仮想記憶環境下ではハードディスクもフルになっているので、ファイルへの追記さえ危ういですし。OSのログに期待です。 せめて悪させずにプロセス終了することくらいなら、なんとかテストできないかなと思います。メモリ不足時、単にプロセス終了しかしてなければ、VirtualAllocを使ってのテストは有効と感じてます。
guest

0

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

参考情報:

...
デバッガで無理矢理通す
...

投稿2015/11/21 11:15

katoy

総合スコア22324

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

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

Chironian

2015/11/21 12:52 編集

ご回答、ありがとうございます。 実際に実施されているのですね。 費用対効果の低いテストなので悩ましいです。コストを下げることができるとよいのですが... 【追記】 たぶん、newをオーバーロードしてn回目でbad_allocできるコードを作れればそこそこ良いテストができそうですね。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問