Exception externe C0000006
j'ai écrit un programme dans Delphi et quand je l'exécute à partir d'un disque sur la clé. À un moment donné, je dois débrancher le disque sur la touche pendant que l'application est en cours d'exécution. Si je fais ça sur un ordinateur avec au moins 1 Go de mémoire vive, tout va bien. Quand je fais cela sur une machine avec 512 Mo j'obtiens une exception externe C0000006. Si Je ne me trompe pas, c'est parce que L'OS essaye de lire la ligne suivante de code mais ne peut pas trouver la ressource pour elle (ce qui signifie que l'application n'a pas été chargée sur la ram) ce qui est absurde car c'est une application de 500kb.
comment résoudre ce problème? ou au moins gérer cette exception d'une manière plus élégante? (Puisque je ne peux pas l'attraper puisque c'est une exception externe).
Oh, et mon application Delphi est une application console sous windows xp.
6 réponses
ce que vous devez faire est de dire à windows de charger l'ensemble de votre programme en mémoire, plutôt que de lui permettre de demander des pages de chargement quand il en a besoin. Je l'ai fait avec succès pour des applications tournant sur un CD. Je n'ai pas le code avec moi en ce moment, mais je me rappelle que j'ai trouvé des conseils sur la façon de le faire dans la source pour le fantastique programme D'installation open source Inno Setup.
Edit: en fait, après avoir fait un peu de recherche, vous pouvez utiliser une directive de compilateur Delphi pour dire windows pour charger l'exécutable complet. Cela fonctionne si vous avez Delphi > 2006. Cela aura pour effet que vous n'obtiendrez jamais l'externe exception.
mettez cette ligne dans votre dossier de projet d'applications:
{$SetPEFlags IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP}
cela indique à windows que l'exécutable va être utilisé à partir de supports amovibles, donc chargez l'exécutable en mémoire (ou le fichier swap). Alors vous n'avez pas besoin de vous soucier de choses comme copier le fichier sur la machine en premier, etc.
Edit 2: j'ai actuellement accès à Delphi 7 et je peux confirmer, comme noté par d'autres, que cela fonctionne aussi avec Delphi 7 (et probablement Delphi 6) avec le code suivant:
const
IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP = 00;
{$SetPEFlags IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP}
Pour Delphi < 6, vous pouvez aller sur le chemin de forcer l'exécutable à être envoyés. Il est un exemple de comment le faire en C++ ici (à moins que vous ne trouviez un moyen de modifier les drapeaux D'en-tête PE après l'heure du lien, qui semble être compliqué)
N@
C'est EXCEPTION_IN_PAGE_ERROR
. Cela signifie que le chargeur D'OS n'a pas réussi à mettre en page certaines données requises pour l'application à exécuter, probablement en raison d'une erreur d'E/S ou d'une autre erreur. Puisque vous retirez le disque, ça aurait du sens.
peut-être l'ensemble de travail (l'ensemble des pages de mémoire souvent utilisées) pour l'application a été autorisé à croître assez grand sur les machines de 1 Go de sorte que le recours au disque pour recharger des pages n'était pas nécessaire, mais ce n'était pas le cas sur les machines de 512 Mo?
je suggérerait d'essayer de copier l'exécutable à un emplacement temporaire et de le démarrer à partir de là, éventuellement avec suppression retardée; ou utiliser un autre mécanisme pour garantir le support sur le disque pour toutes les pages de mémoire touchées par l'application dans l'utilisation normale, et de prévenir cette erreur en cas de pression de mémoire, où L'OS va couper l'ensemble de travail des processus en cours d'exécution.
comme @Barry, je recommande de vérifier le type de lecteur du volume d'où votre exécutable s'exécute; s'il s'agit d'un lecteur amovible (et s'il manque un paramètre de ligne de commande "déjà en temp"), copiez l'exécutable (et ses dépendances) à l'adresse
- créer chaque fichier temporaire en utilisant
File.Create(targetPath, bufferSize, FileOptions.DeleteOnClose)
(ou l'un des FileOptions paramètre), mais assurez-vous de tenir sur leFile
instance jusqu'à ce que après la seconde copie est lancée (par exemple dans unList<File>
). - Copier le contenu de chaque fichier.
- lancer l'exécutable à partir du dossier temp.
- Appel
Close()
sur chacune desFile
instances sauvegardées ci-dessus. - quitter l'exécutable original.
de cette façon, les dossiers se ferment peu importe lequel le processus se termine d'abord, et le volume source peut être enlevé plus tôt.
la solution
uses Windows;
{$SetPEFlags IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP or IMAGE_FILE_NET_RUN_FROM_SWAP}
est disponible pour Delphi depuis la version 6.
Il y a un Delphi version de travail RunImageLocally from MSJ ce qui force l'exécutable/dll à être bipé. Cela peut prévenir les erreurs C0000006 lors de l'exécution à partir d'un réseau ou d'un support amovible...
Check it out https://github.com/jrsoftware/issrc/blob/master/Projects/SetupLdr.dpr
cette exception C0000006 se produit aussi souvent si votre logiciel est exécuté à partir d'un lecteur réseau. Pour éviter ce problème, vous pouvez combiner le drapeau
{$SetPEFlags IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP}
IMAGE_FILE_NET_RUN_FROM_SWAP = 00;
{$SetPEFlags C00}