English follows Japanese.


気がついたらGoogle先生がE_INVALIDARGの第一候補として推薦してくれるようになりました。
先生ありがとうございます。ですが、このページは本来のE_INVALIDARGとはほとんど無関係です。

あまりにも申し訳ないのでE_INVALIDARGのちゃんとした内容を載せておきます。
[2009/07/25 追記] ランクは下がったものの、未だ先生から飛ばされてくる方が多いのでもう少しちゃんとした記事を書きます。

E_INVALIDARG (80070057)

Component Object Model (COM)のエラーの一つ。引数の値が不正なことを示す。

Reason Method call with an invalid argument.
HRESULT 0x80070057
Severity Failure
Facility Win32
Code 0x57

 

一般のパソコンユーザの方へ

エラー画面などでこの番号を見た場合、こんなことが起こっている可能性があります。

  • 入力欄に何も入れていない場合、空白/改行だけ入れた場合、”半角で”という場所に全角で入れた場合やその逆
  • 入力ファイルの中身が無い場合、ファイルそのものがない場合
  • プログラムを作った人が思いもしない使い方をした場合
     (前兆として0x80004005 や E_FAIL というのが出る場合はこれ)
  • そのプログラムを使うのに必要な別のプログラムを削除した場合
     (前兆として0x80004002 や E_NOINTERFACE というのが出る場合はこれ)

プログラムの種類にもよりますが、ネットワークを使うプログラムでコレを見た場合は入力関係のミス、音楽動画再生の場合はファイルに問題、ゲームなどの場合はスペック不足が原因であることが多いです。

あとプログラムが書き込み処理をしている最中に電源を落としたり、プログラムを強制停止させたりして、プログラムの実行に必要なファイルが壊れてしまった場合にもこのエラーが出ます。安易にレジストリを操作するツールを使った場合もこの種のエラーが出ます。この場合、データをバックアップしてプログラムを再インストールすると直るケースが多いです。再インストールするときは、一度アンインストールしてから再インストールしてください。

ちなみにこのエラーは本来「一般ユーザに見せるべきではないエラー」です。いうなれば、「税理士/行政書士にお願いした書類が役所から内容不備で返ってきた」という内容に近い恥ずかしいエラーです。言い訳をすると、プログラムが「ユーザが入力した値は100%正しい」と思って動いている証拠でもあります。

市販ソフトウェアの場合サポートに連絡をするのが良いと思いますが、対応は「何かの入力ミスですぐ解決」になるか「もう少し詳しい状況を~ 。~というファイルを送っていただいて~ 折り返し~」という非常に手間と時間がかかることになるかのどちらかです。後者の場合、開発者でないとわからない何かまずい状況が起きていて窓口では対応しきれない状況だということが多いです。

無償ソフトウェアや有志による自作ソフトウェアの場合「想定外でした ごめんなさい (0x80070057)」という意図で出していることが多いので、あまり解決は期待できないかもしれません。ですが、「こういう状況でこういう操作をしたらコレが出ました」と一報を入れると感謝されることでしょう。

プログラマの方へ

たいていの場合、次のようなケースです。

  • LPTSTRにNULLを渡した
  • LPVOID*にNULLを渡した
  • [size_is(len)] unsigned char * ptr, int lenでlenに負を渡した
  • 配列を扱う関数にindexを渡すとき、indexが有効な範囲から外れている
  • enumの引数に対して、定義されていないenumの値を入れた
  • ある引数とある引数の関係が矛盾している (長さ10の配列に対してインデックス番号が11番目など)
  • 個数を入れるところに自然数でない数値を入れた

それ以外ですと、構造体のサイズがおかしい場合、reservedの値がいじられている場合、ConnectionPointとして渡すインタフェースのQueryに失敗した場合などに上げられるときもあります。最後はE_NOINTERFACEの方がしっくりくる気もしますが。

あとMSDNでサラッと流されてますが、CoInitialize/CoInitializeExの返値としてE_INVALIDARGが返る場合があります。フリースレッドの場合、スレッド依存のエラーになりやすいので注意しましょう。COM関数全てにFAILED()のエラーハンドリングを入れると良いでしょう。特にDCOMを使う場合は必須です。

基本、デバッグ時にASSERTで引っかけるべき項目であることが多いです。対策としては多少過剰なくらいガード節を入れ、そもそも呼び先の関数に過大な期待をしていないか確認してみると良いと思います (たとえば「長さ0の配列の0番目の0バイト目から0バイトをコピー」は成功するべきだろう など)。また、守備範囲が明確になっていない関数ほどこのエラーを受けやすい傾向にあります。本来であれば受け付けるべきではない(自分がE_INVALIDARGを返すべき)処理を引き受け、それを下に丸投げしてE_INVALIDARGを返され、しかも不用意にステートを変えてしまったために復帰できずE_FAILとして上に返すケースは最悪です。

上の話に関連しますが、E_INVALIDARGを返す場合は内部ステートを変えない状態 (逐次再利用可能な状態) で起こすのが望ましいです。たとえばバッファ不足が処理本体に入る前に検出できるならE_INVALIDARG(不正引数)を、実行してみて初めてわかる場合はE_FAIL(失敗)やE_OUTOFMEMORY(メモリ不足)を、実行した後に復帰するAPIを呼び出せば逐次再利用可能な状態に戻せる場合はE_ABORT(中断)を返すのが良いと思います。

以下、参考資料です。

[余談]
コンピュータ関連のキーワードは他に重要(ページランク高値)なものが多いので、こんなくだらないページが上位にはこないはずなのですが…


In this blog, I describe the true meanings of E_INVALIDARG because Google suggests this page as the top result of the word, ‘E_INVALIDARG’.

E_INVALIDARG (80070057)

One of the error defined in Component Object Model(COM).
A function returns E_INVALIDARG when you passed an invalid argument.

Reason Method call with an invalid argument.
HRESULT 0x80070057
Severity Failure
Facility Win32
Code 0x57

 

A COM function returns E_INVALIDARG if…

  • An pointer passed to a function is a null.
  • An index is out of range.
  • A data member ‘cbSize’ has an invalid size of a structure.

If you are an user of a software, it may caused by your slight mistake or the software maker’s serious mistake.

If you are a developer of a software, you should check your code with much attention.  It is effective to introduce “Guard Clause” to your code to avoid wrong function calls and damage to your main procedure caused by wrong arguments.  Normally, you should reject the wrong arguments by passing ‘E_INVALIDARG’ to callers.

According to the MSDN article, it will be also returned by CoInitialize and CoInitializeEx.

See also