What happens if external code throws an exception?

In VFP, there are many features to call external code, such as ActiveX controls, COM servers, DECLARE DLL or SET LIBRARY TO. In older versions, you could even LOAD and CALL machine code. If such external calls caused a crash for some reason, what should happen? In VFP5 and earlier, the exception was unhandled, and the process would crash, with the user not having much indication of why.

Try this code that will copy a string using memcpy:

DECLARE integer memcpy IN msvcrt string @ dest , string src, integer

csrc="String to copy"

cdest=SPACE(LEN(csrc))

memcpy(@cdest,csrc,LEN(csrc))

?"dest=",cdest

Now suppose the user made the call incorrectly, passing an integer of 0 as the destination. Since you don’t have the right to access memory at location 0, an Access Violation exception occurs:

DECLARE integer memcpy IN msvcrt string @ dest , string src, integer

csrc="String to copy"

cdest=SPACE(LEN(csrc))

memcpy(0,csrc,LEN(csrc))

?"dest=",cdest

VFP yields an error Declare DLL call caused an exception.

(BTW, passing an integer 0 to a DLL with a declared parameter of byref string is a feature I added back around the vfp5 timeframe. It only works with 0, because sometimes you want to pass a NULL pointer rather than an empty string)

You can also try this with a VFP COM dll: using SYS(1079) (see Intentionally crash your program)

x=CREATEOBJECT("t1.c1")

x.myeval("sys(1079)")

An error occurs: OLE IDispatch exception code 5 from t1.c1 t1.c1: .myeval d:\fox90\test\c1.prg Error in line 5 -1073741819..

And surprise surprise: convert the number to hexadecimal:

?TRANSFORM(-1073741819,"@0x")

which displays 0xC0000005

If you use early binding (not IDispatch), you get a different error:

x=CREATEOBJECTEX("t1.c1","","")

x.myeval("sys(1079)")

or

x=CREATEOBJECT("t1.c1")

y=GETINTERFACE(x,"Ic1")

y.myeval("sys(1079)")

OLE exception error: Exception code c0000005. OLE object may be corrupt

What changed so that the crash doesn’t destroy the VFP process? The call is handled by a try-except statement, which cuases the error message, rather than a crash.

When this occurs, something went wrong with the called code, and it may not have had a chance to clean up after itself. For example, the server might have opened a resource or allocated some memory, then caused the exception. That’s why the message says “may be corrupt”.