Внешнее исключение C0000006
Я написал некоторую программу в Delphi и когда я запускаю ее с диска на ключ. В какой-то момент мне нужно отключить диск на клавиатуре во время работы приложения. Если я сделаю это на компьютере с по крайней мере 1 гб RAM, все будет в порядке. Когда я делаю это на машине с 512mb, я получаю внешнее исключение C0000006. Если я не ошибаюсь, это связано с тем, что ОС пытается прочитать следующую строку кода, но не может найти ресурс для нее (что означает, что приложение не было загружено в RAM), что является абсурдным, потому что это приложение 500 КБ.
Как я могу это решить? или, по крайней мере, справиться с этим исключением более элегантным способом? (Так как я не могу его поймать, поскольку это внешнее исключение).
О, и мое приложение Delphi представляет собой консольное приложение под Windows XP.
Ответы
Ответ 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.
Ответ 5
Существует рабочая версия Delphi RunImageLocally из MSJ, которая заставляет загружать исполняемый файл /dll. Это может предотвратить ошибки C0000006 при запуске из сетевой или съемный носитель...
Проверьте это на https://github.com/jrsoftware/issrc/blob/master/Projects/SetupLdr.dpr
Ответ 6
Это исключение C0000006 также часто возникает, если ваше программное обеспечение запускается с сетевого диска. Чтобы предотвратить эту проблему, вы можете комбинировать флаг
{$SetPEFlags IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP}
со следующим флагом:
IMAGE_FILE_NET_RUN_FROM_SWAP = $0800;
{$SetPEFlags $0C00}