External exception C0000006
Asked Answered
P

6

23

I've wrote some program in Delphi and when I am running it from a disk on key. At some point I'm required to unplug the disk on key while the application is running. If I do this on a computer with at least 1gb of ram everything is okay. When I do this on a machine with 512mb I get an external exception C0000006. If I'm not mistaken, this is because the OS is trying to read the next line of code but cannot find the resource for it (meaning, the application wasn't loaded to the ram) which is absurd because it's a 500kb application.

How can I solve this? or at least handle this exception in a more elegant way? (Since I can't catch it since it's an external exception).

Oh, and my Delphi application is a console application under windows xp.

Proud answered 23/8, 2009 at 5:59 Comment(1)
0xC0000006 and other exceptions are listed here: support.tabs3.com/main/R10309.htmZinazinah
L
38

What you need to do is tell windows to load your whole program into memory, rather than allowing it to demand load pages when it needs to. I have done this successfully for applications running off a CD. I don't have the code with me right now, but I recall that I found hints on how to do it in source for the fantastic open source install program Inno Setup.

Edit: Actually, after doing a little research, you can use a Delphi compiler directive to tell windows to load the full executable. This works if you have Delphi > 2006. This will have the effect that you will never get the external exception.

Put this line in your applications project file:

{$SetPEFlags IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP}

This tells windows that the executable is going to be used from removable media, so load the the executable into memory (or the swap file). Then you don't need to worry about things like copying the file to the machine first, etc.

Edit 2: I currently have access to Delphi 7 and I can confirm, as noted by others, that this also works with Delphi 7 (and likely Delphi 6) with the following code:

const
  IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP = $0400;

{$SetPEFlags IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP}

For Delphi < 6, you can go down the path of forcing the executable to be paged in. There is an example of how to do it in C++ here (unless you find a way to modify the PE header flags after link time, which looks to be complicated)

N@

Laband answered 23/8, 2009 at 9:0 Comment(7)
Where in the project file should it be?Caber
Anywhere I think, but I have put it below the program line before.Laband
@Nat. This directive is supported in D2006. See my question #6905895Goodill
Yes, I know. That's why I have '< D2006' rather than '< D2007' :)Laband
@Nat: Any idea how to set it for Delphi 7?Amusing
@Amusing I believe there are some tools on the net which can set header flag after compilation. Don't know of any off the top of my head.Laband
Use editbin from MS VS. The command is editbin /SWAP:CD your_exeDanilodanio
F
17

That's EXCEPTION_IN_PAGE_ERROR. It means that the OS loader failed to page in some data required for the application to run, probably due to an I/O error or other error. Since you're removing the disk, that would make sense.

Perhaps the working set (the set of often-used memory pages) for the application was allowed to grow large enough on 1GB machines such that recourse to the disk to reload pages wasn't necessary, but that wasn't the case on 512MB machines?

I would suggest trying to copy the executable to a temporary location and starting it from there, possibly with delayed deletion; or use some other mechanism to guarantee on-disk backing for all memory pages touched by the application in normal use, and prevent this error in cases of memory pressure, where the OS will trim the working set of running processes.

Footpad answered 23/8, 2009 at 7:2 Comment(2)
Where did you look that up to find out what sort of error it is?Baptism
The EXCEPTION_ codes in winbase.h; they are generally synonyms for corresponding NTSTATUS codes from winnt.h.Footpad
X
4

Like @Barry, I would recommend checking the drive type of the volume that your executable is running from; if it is a removeable drive (and missing a "already in temp" command line parameter) copy the executable (and any of its dependencies) to the user's %TEMP% folder and then re-launch it from there with an extra command line parameter to indicate "already in temp".

  1. Create each temporary file using File.Create(targetPath, bufferSize, FileOptions.DeleteOnClose) (or one of the FileStream constructors that takes a FileOptions parameter), but make sure to hang onto the returned File instance until after the second copy is launched (e.g. in a List<File>).
  2. Copy the contents of each file.
  3. Launch the executable from the temp folder.
  4. Call Close() on each of the File instances saved above.
  5. Exit the original executable.

This way the files get closed regardless of which process finishes first, and the source volume can be removed earlier.

Xanthochroid answered 23/8, 2009 at 13:16 Comment(0)
M
1

The solution

uses Windows;
{$SetPEFlags IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP or IMAGE_FILE_NET_RUN_FROM_SWAP}

is available for Delphi since version 6.

Minni answered 9/11, 2017 at 13:13 Comment(0)
T
0

There's a Delphi working version of RunImageLocally from MSJ which forces the executable/dll to be paged in. This can prevent C0000006 errors when running from network or removable media...

Check it out at https://github.com/jrsoftware/issrc/blob/master/Projects/SetupLdr.dpr

Terylene answered 17/8, 2015 at 17:42 Comment(0)
E
0

This exception C0000006 also often occurs if your software is run from a network drive. To prevent that problem you can combine the flag

{$SetPEFlags IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP}

with the following flag:

IMAGE_FILE_NET_RUN_FROM_SWAP = $0800;

{$SetPEFlags $0C00}
Elle answered 28/1, 2016 at 8:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.