Partager via


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”.

Comments

  • Anonymous
    November 20, 2005
    Calvin, very interesting. From a developer's point-of-view (who is still on VFP 8 for many technical and practical reasons), are you saying try catch can avoid the dreaded 0xc00000005 error (if you find a piece of code that produces that)? I appreciate your blog immensely, thank. Don

  • Anonymous
    November 20, 2005
    I should have been more clear. The C++ try-except statement wraps calls to external code, so exceptions in external code are caught, not the VFP program that's running. Internal exceptions are caught and show the Watson dialog

  • Anonymous
    April 24, 2006
    I was writing a sample about DECLARE DLL to show some of its features which I implemented about 12 years...

  • Anonymous
    July 18, 2006

    is any possibilites that socket of c++ can through  this exception?

  • Anonymous
    June 20, 2008
    PingBack from http://jesse.finestmatingstories.com/exceptioncode.html

  • Anonymous
    June 14, 2009
    PingBack from http://patiocushionsource.info/story.php?id=2233