Подтвердить что ты не робот

Внешнее исключение C0000006

Я написал некоторую программу в Delphi и когда я запускаю ее с диска на ключ. В какой-то момент мне нужно отключить диск на клавиатуре во время работы приложения. Если я сделаю это на компьютере с по крайней мере 1 гб RAM, все будет в порядке. Когда я делаю это на машине с 512mb, я получаю внешнее исключение C0000006. Если я не ошибаюсь, это связано с тем, что ОС пытается прочитать следующую строку кода, но не может найти ресурс для нее (что означает, что приложение не было загружено в RAM), что является абсурдным, потому что это приложение 500 КБ.

Как я могу это решить? или, по крайней мере, справиться с этим исключением более элегантным способом? (Так как я не могу его поймать, поскольку это внешнее исключение).

О, и мое приложение Delphi представляет собой консольное приложение под Windows XP.

4b9b3361

Ответ 1

Что вам нужно сделать, так это сказать, что Windows загружает всю вашу программу в память, а не позволяет ей требовать загрузки страниц, когда это необходимо. Я сделал это успешно для приложений, запущенных с компакт-диска. У меня нет кода со мной прямо сейчас, но я помню, что я нашел подсказки о том, как это сделать в источнике для фантастической программы установки Inno с открытым исходным кодом.

Изменить: Собственно, после небольшого исследования вы можете использовать директиву компилятора Delphi, чтобы сообщить Windows о загрузке полного исполняемого файла. Это работает, если у вас есть Delphi > 2006. Это приведет к тому, что вы никогда не получите внешнее исключение.

Поместите эту строку в файл проекта приложений:

{$SetPEFlags IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP}

Это говорит Windows, что исполняемый файл будет использоваться со съемных носителей, поэтому загрузите исполняемый файл в память (или файл подкачки). Тогда вам не нужно беспокоиться о таких вещах, как копирование файла на машину и т.д.

Для Delphi < 2006, вы можете пойти по пути принудительного выполнения исполняемого файла. Существует пример того, как это сделать в С++ здесь (кроме вы найдете способ изменить флаги заголовков PE после времени ссылки, что выглядит сложным)

N @

Ответ 2

Это EXCEPTION_IN_PAGE_ERROR. Это означает, что загрузчик ОС не смог выполнить поиск некоторых данных, необходимых для запуска приложения, вероятно, из-за ошибки ввода-вывода или другой ошибки. Поскольку вы удаляете диск, это имеет смысл.

Возможно, для рабочего набора (набора часто используемых страниц памяти) для приложения было разрешено достаточно расти на машинах 1 ГБ, так что обращение к диску для перезагрузки страниц было необязательным, но это было не так на машинах с 512 МБ?

Я бы предложил попробовать скопировать исполняемый файл во временное место и запустить его оттуда, возможно с задержкой удаления; или использовать какой-либо другой механизм для обеспечения поддержки на диске для всех страниц памяти, затронутых приложением в обычном режиме, и предотвратить эту ошибку в случае давления памяти, когда ОС будет обрезать рабочий набор запущенных процессов.

Ответ 3

Как и @Barry, я бы рекомендовал проверить тип диска тома, из которого выполняется ваш исполняемый файл; если это удаляемый диск (и отсутствует параметр командной строки "уже в temp" ), скопируйте исполняемый файл (и любые его зависимости) в пользовательскую папку %TEMP%, а затем снова запустите его с дополнительным параметром командной строки для обозначения "уже в темпе".

  • Создайте каждый временный файл с помощью File.Create(targetPath, bufferSize, FileOptions.DeleteOnClose) (или одного из конструкторов FileStream, который принимает параметр FileOptions), но обязательно верните его в возвращаемый экземпляр File до после запускается вторая копия (например, в List<File>).
  • Скопировать содержимое каждого файла.
  • Запустите исполняемый файл из папки temp.
  • Вызовите Close() для каждого из экземпляров File, сохраненных выше.
  • Выход из исходного исполняемого файла.

Таким образом, файлы закрываются независимо от того, какой процесс заканчивается первым, а исходный том может быть удален ранее.

Ответ 4

Решение

uses Windows;
{$SetPEFlags IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP or IMAGE_FILE_NET_RUN_FROM_SWAP}

доступен для Delphi с версии 6.

Ответ 6

Это исключение C0000006 также часто возникает, если ваше программное обеспечение запускается с сетевого диска. Чтобы предотвратить эту проблему, вы можете комбинировать флаг

{$SetPEFlags IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP}

со следующим флагом:

IMAGE_FILE_NET_RUN_FROM_SWAP = $0800;

{$SetPEFlags $0C00}