web-dev-qa-db-ja.com

外部例外C0000006

Delphiでいくつかのプログラムを作成し、ディスクオンキーから実行しているとき。ある時点で、アプリケーションの実行中にディスクオンキーを取り外す必要があります。少なくとも1 GBのRAMが搭載されたコンピューターでこれを行うと、すべてが問題ありません。 512MBのマシンでこれを行うと、外部例外C0000006が発生します。私が誤解していないのは、OSが次のコード行を読み取ろうとしているのに、そのリソースが見つからない(つまり、アプリケーションがRAMにロードされなかった)ためです。

どうすればこれを解決できますか?または、少なくともこの例外をよりエレガントな方法で処理しますか? (それは外部の例外なのでそれをキャッチすることができないので)。

ああ、私のDelphiアプリケーションはWindows XPのコンソールアプリケーションです。

21
Luke

あなたがする必要があるのは、必要なときにロードページを要求するのではなく、プログラム全体をメモリにロードするようにWindowsに指示することです。 CDから実行されているアプリケーションに対して、これを正常に実行しました。私は現在コードを持っていませんが、素晴らしいオープンソースインストールプログラムInno Setupのソースでそれを行う方法のヒントを見つけたことを思い出します。

編集:実際、少し調べた後、Delphiコンパイラディレクティブを使用して、Windowsに実行可能ファイル全体をロードするように指示できます。これは、Delphi> 2006の場合に機能します。これにより、外部例外が発生しないという効果があります。

次の行をアプリケーションプロジェクトファイルに追加します。

{$SetPEFlags IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP}

これは、実行可能ファイルがリムーバブルメディアから使用されることをウィンドウに通知するため、実行可能ファイルをメモリ(またはスワップファイル)にロードします。その後、最初にファイルをマシンにコピーするなどのことを心配する必要はありません。

編集2:現在Delphi 7にアクセスしており、他の人が指摘しているように、これがDelphi 7(およびおそらくDelphi 6)でも機能することを確認できます)次のコードで:

const
  IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP = $0400;

{$SetPEFlags IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP}

Delphi <6の場合、実行可能ファイルを強制的にページインするパスをたどることができます。C++で実行する方法の例があります here (PEヘッダーを変更する方法が見つからない限り)リンク時のフラグ。複雑に見えます)

N @

37
Nat

それはEXCEPTION_IN_PAGE_ERROR。これは、おそらくI/Oエラーまたはその他のエラーが原因で、OSローダーがアプリケーションの実行に必要な一部のデータをページインできなかったことを意味します。ディスクを削除するので、それは理にかなっています。

おそらく、アプリケーションのワーキングセット(頻繁に使用されるメモリページのセット)を1GBマシンで十分に大きくできるため、ディスクを使用してページをリロードする必要はありませんでしたが、512MBマシンではそうではありませんでした。 ?

実行可能ファイルを一時的な場所にコピーして、そこから開始することをお勧めします。削除が遅れる可能性があります。または、他のメカニズムを使用して、通常の使用時にアプリケーションがアクセスするすべてのメモリページのディスク上のバッキングを保証し、OSが実行中のプロセスのワーキングセットをトリミングするメモリ不足の場合にこのエラーを防止します。

17
Barry Kelly

@Barryと同様に、実行可能ファイルが実行されているボリュームのドライブタイプを確認することをお勧めします。それがリムーバブルドライブである場合(および「一時的にすでに」コマンドラインパラメーターがない場合)、実行可能ファイル(およびその依存関係のいずれか)をユーザーの_%TEMP%_フォルダーにコピーし、追加のコマンドを使用してそこから再起動します。 「temped in temp」を示す行パラメータ。

  1. File.Create(targetPath, bufferSize, FileOptions.DeleteOnClose)(またはFileStreamパラメーターを受け取るFileOptionsコンストラクターの1つ)を使用して各一時ファイルを作成しますが、返されたFileを必ず確認してくださいインスタンスまでafter 2番目のコピーが起動されます(例:_List<File>_)。
  2. 各ファイルの内容をコピーします。
  3. Tempフォルダーから実行可能ファイルを起動します。
  4. 上記で保存したFileインスタンスのそれぞれでClose()を呼び出します。
  5. 元の実行可能ファイルを終了します。

この方法では、最初に終了するプロセスに関係なくファイルが閉じられ、ソースボリュームをより早く削除できます。

4
devstuff

ソリューション

uses Windows;
{$SetPEFlags IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP or IMAGE_FILE_NET_RUN_FROM_SWAP}

バージョン6以降のDelphiで使用できます。

1
Moje Meno

この例外C0000006は、ソフトウェアがネットワークドライブから実行されている場合にも発生します。その問題を防ぐために、フラグを組み合わせることができます

{$SetPEFlags IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP}

次のフラグで:

IMAGE_FILE_NET_RUN_FROM_SWAP = $0800;

{$SetPEFlags $0C00}
0
GHN

Delphiの動作バージョン MSJからのRunImageLocally があり、実行可能ファイル/ dllが強制的にページインされます。これにより、ネットワークまたはリムーバブルメディアから実行しているときのC0000006エラーを防ぐことができます...

https://github.com/jrsoftware/issrc/blob/master/Projects/SetupLdr.dpr で確認してください。

0
phs.bnu