Discussion:
Can't seem to catch exception
(too old to reply)
Brian
2010-02-08 18:59:31 UTC
Permalink
I have a program that creates an object, destroys it, and then tries
to access it. The intent here is to cause and exception and then to
catch it. Thing is, I can't seem to catch it. Here is my program.

Any ideas why I can't seem to catch it?

brian

program Greeting;


{$APPTYPE CONSOLE}

uses
Unit1,
sysutils;


type
PCar = ^TCar;

var
myCar:TCar;
myPCar: PCar;

begin
bar := 20;
myCar.Create;
myPCar := @myCar;

myCar.Destroy;

try
Writeln('the car is running ', myCar.getRunning );
except
on Exception do Beep;
end;

end.

Here is Unit1.pas in case you want to see the code to it as well.

nit Unit1;


interface

type TCar = class
private
Frunning: boolean;
public
procedure Start;
procedure Stop;
function getRunning: boolean;
end;

implementation

procedure TCar.Start;
begin
Frunning := true;
end;

procedure TCar.Stop;
begin
Frunning := false;
end;

function TCar.getRunning: boolean;
begin
result := Frunning;
end;

end.
Anonymous
2010-02-08 21:32:45 UTC
Permalink
Post by Brian
I have a program that creates an object, destroys it, and then tries
to access it. The intent here is to cause and exception and then to
catch it. Thing is, I can't seem to catch it. Here is my program.
Any ideas why I can't seem to catch it?
brian
program Greeting;
{$APPTYPE CONSOLE}
uses
Unit1,
sysutils;
type
PCar = ^TCar;
var
myCar:TCar;
myPCar: PCar;
begin
bar := 20;
myCar.Create;
myCar.Destroy;
try
Writeln('the car is running ', myCar.getRunning );
except
on Exception do Beep;
end;
end.
Here is Unit1.pas in case you want to see the code to it as well.
nit Unit1;
interface
type TCar = class
private
Frunning: boolean;
public
procedure Start;
procedure Stop;
function getRunning: boolean;
end;
implementation
procedure TCar.Start;
begin
Frunning := true;
end;
procedure TCar.Stop;
begin
Frunning := false;
end;
function TCar.getRunning: boolean;
begin
result := Frunning;
end;
end.
I had a problem once getting sound/beeps out of a dll. Not
sure if this is the same problem with a console. Try checking
a switch or something else to see if you get a hit.
Maarten Wiltink
2010-02-08 22:02:45 UTC
Permalink
Post by Brian
I have a program that creates an object, destroys it, and then tries
to access it. The intent here is to cause and exception and then to
catch it. Thing is, I can't seem to catch it. Here is my program.
Any ideas why I can't seem to catch it?
Not another one, please.

When you destroyed the object, you invalidated the reference. You took
away your own right to use that object - but you are not entitled to
exceptions when you do. You can't catch the exception because there
isn't one.

There is something you could do to make that code generate an exception,
but I'd much rather not tell you because you'd probably draw the wrong
conclusion from it.

The truth is that you destroyed the object and it is now up to you not
to try and use it. Write your code so it doesn't; you know how. Don't
try to wring exceptions from circumstances that hold no promises of
them.

If you want an exception to be raised, the syntax is
"raise Exception.Create('<Message>');".

Groetjes,
Maarten Wiltink
Brian
2010-02-10 18:34:24 UTC
Permalink
Post by Maarten Wiltink
Post by Brian
I have a program that creates an object, destroys it, and then tries
to access it. The intent here is to cause and exception and then to
catch it. Thing is, I can't seem to catch it. Here is my program.
Any ideas why I can't seem to catch it?
Not another one, please.
When you destroyed the object, you invalidated the reference. You took
away your own right to use that object - but you are not entitled to
exceptions when you do. You can't catch the exception because there
isn't one.
There is something you could do to make that code generate an exception,
but I'd much rather not tell you because you'd probably draw the wrong
conclusion from it.
The truth is that you destroyed the object and it is now up to you not
to try and use it. Write your code so it doesn't; you know how. Don't
try to wring exceptions from circumstances that hold no promises of
them.
If you want an exception to be raised, the syntax is
"raise Exception.Create('<Message>');".
Groetjes,
Maarten Wiltink
This is just test code. I know the object is invalid. I purposely did
it that way! It seems that this ought to throw a catchable exception
rather than going to the OS and presenting the user with error address
0x00ff3344.
Rudy Velthuis
2010-02-10 19:39:43 UTC
Permalink
Post by Brian
This is just test code. I know the object is invalid. I purposely did
it that way! It seems that this ought to throw a catchable exception
It doesn't have to do anything like it. Accessing freed objects causes
undefined behaviour. If you are lucky, you might get an AV. But you
don't have to be lucky. The behaviour is, well, undefined.
--
Rudy Velthuis http://rvelthuis.de

"He is a self-made man and worships his creator."
-- John Bright
Maarten Wiltink
2010-02-10 22:08:36 UTC
Permalink
"Brian" <***@brie.com> wrote in message news:209ab226-336c-46dc-9f43-***@t17g2000prg.googlegroups.com...
[...]
Post by Brian
This is just test code. I know the object is invalid. I purposely did
it that way!
Well, don't.

I'm quite serious. Programming languages have specifications (however
poor, and this is not one of Delphi's strong points), and if you don't
stick to them, you do not get to complain.

The specification says you aren't allowed to use invalid object
references. It may or may not say that it's up to you to know which
object references are valid and which ones are not, but it might and
arguably it should. It's not exactly rocket science, either.

Groetjes,
Maarten Wiltink
Rob Kennedy
2010-02-11 03:59:40 UTC
Permalink
Post by Brian
This is just test code. I know the object is invalid. I purposely did
it that way! It seems that this ought to throw a catchable exception
rather than going to the OS and presenting the user with error address
0x00ff3344.
Ah, you didn't mention that there was an error message, but that was an
important clue. You're seeing an exception, but you're wondering why
your code doesn't catch it. The reason is that the exception you're
seeing is the exception you expected to get.

Here's the line of code that's raising the exception:

myCar.Create;

Didn't the compiler warn you that that variable might be undefined? Use
the object-creation code you've seen a million times before:

myCar := TCar.Create;

The way you're calling the constructor, it assumes there's already a
valid object reference in myCar and it just calls Create to
re-initialize all that object's fields. But there is no object being
referenced. That variable holds garbage, so there are no fields to
initialize.

Your try-finally block didn't include that line. Even if it had, there's
still no guarantee you'd get an exception. If the garbage value in myCar
happens to be an address that belongs to your process and is writable,
your program might accidentally run just fine.
--
Rob
Hans-Peter Diettrich
2010-02-09 02:53:23 UTC
Permalink
Post by Brian
I have a program that creates an object, destroys it, and then tries
to access it. The intent here is to cause and exception and then to
catch it.
Destroyed objects do not normally throw exceptions when accessed, what
makes it hard to find such bugs.

Try FreeAndNil(myCar);

DoDi
Brian
2010-02-10 18:32:03 UTC
Permalink
Post by Hans-Peter Diettrich
Post by Brian
I have a program that creates an object, destroys it, and then tries
to access it. The intent here is to cause and exception and then to
catch it.
Destroyed objects do not normally throw exceptions when accessed, what
makes it hard to find such bugs.
Try FreeAndNil(myCar);
DoDi
Hmm, I'll check this out.

brian
BRoberts
2010-02-14 20:13:51 UTC
Permalink
Post by Brian
I have a program that creates an object, destroys it, and then tries
to access it. The intent here is to cause and exception and then to
catch it. Thing is, I can't seem to catch it. Here is my program.
Any ideas why I can't seem to catch it?
When you destroy an object the memory allocated to the object is released to
the heap. However any references to that memory are not changed unless you
explicitly do so, e.g. use FreeAndNil or assign nil to the reference.
Subsequently when you use the reference you'll still access the memory but
its contents are undefined. You may or may not get an exception.

If you want to create an exception use a Raise statement, e.g.
Raise Exception.Create ('my Exception');

Loading...