So, I ran into an interesting issue today. We had some UDFs written in cfscript that used try/catch. The object defined in the cfcatch block was var scoped since... well... we always var scope, right? Consider this code block:
function foo() {
var myerror = "";
x = "apple";
try {
if(x+9) x = 1;
} catch(ANY myerror) {
writeOutput(myerror.message & "<p>");
}
}
</cfscript>
<cfoutput>
#foo()#
</cfoutput>
Everything looks hunkey-dorey, right? However, running this will give you: You have attempted to dereference a scalar variable of type class java.lang.String as a structure with members.
Turns out - the var scope of myerror seems to prevent it from being used in the cfcatch block. If you remove the var scope, not only does the code work right, it won't overwrite a variable called myerrors that may exist in the Varibles scope.
Archived Comments
Aw crap! This changes everything. All bets are off. My world is crashing in around me. The horror, the horror!
Seriously, Ray. Good info here. Thx.
How about the scope safe issues... wouldn't you do something like this instead?
<cfscript>
function foo() {
var local = structNew();
var x = "apple";
try {
if(x+9) x = 1;
} catch(ANY local.myerror) {
writeOutput(local.myerror.message & "<p>");
}
}
</cfscript>
<cfoutput>
#foo()#
</cfoutput>
Heh... life gets twisted. (I have also learned on "iteration" calls of functions... the "structNew()" can make execution much slower. So this solution is a spare use function.
You obviously didn't try that code John - catch requires a simple variable name.
Good catch Ray. I'm curious though. What happens if you use try/catch as cf tags (assuming you tried this in a cffunction tag)?
I'm running out the door at the moment, but maybe I'll try this tonight if someone else hasn't.
My, my. One learns something new all the time. Great catch that one!
John - you don't have to worry about it at all. Not var scoping the variable is ok in this case since it won't "leak" out at all.
Please tell me that this is, in fact, a bug and not something that is "intended behavior"
I'm not a Java expert, but someone pointed out that he thought it was the same in Java. Ie, you don't have to pre-declare the variable in the catch block. So maybe that is the reasoning.
Very interesting . . .
Even if you declare myerror as "java.lang.Exception", it still misbehaves. Instead of the dereference error, you get a NullPointerException.
I don’t understand why you are declaring “myerror” any way? It is being declared in catch.
William, the point is that any declared variable in a UDF needs to be var scoped. (Normally.)
I realize this entry topic is getting long in the tooth, and this is probably well understood now. But... my understanding since CF7 is that whatever you put as your exception variable gets automatically scoped to be what we might now call 'local' to the catch block. And this is by design and is what many languages do including, and especially of note, Java: "A local variable may not be redeclared as an exception parameter of a catch... compile-time error occurs". And I supposed, even in CF7, if you put that inside a set of component tags, you would expect the same behaviour as in a plain old inline UDF... No? Since CF sits on the Java, this would not un-expected behaviour.
As far as I know, this is indeed how CFLatest (CF9) works. If I remove the var, run the UDF, the variable isn't leaking out of the UDF. So.. don't var it and don't worry about it. (Again, as far as I know.)
Hmm... seems like cfcatch is still problematic (leaking).
http://daveshuck.com/2011/1...
I realize this thread is ancient, but I just came across the same issue on CF10 and (in light of Henry's comment above) I'm wondering what the recommended workaround for this issue is? Has it been solved? I have been trying to find an answer on this for a while but perhaps my Google Fu is not as strong as it should be. Thoughts?
I am not sure this is a bug, at least not in CF10. The "e" variable in cfcatch is not leaking out into the variables scope.
Thanks for the response Ray. Upon further testing I have confirmed that the cfcatch result is indeed local scoped within the method (CF10).
It still seems like odd behavior since it is inconsistent with other cfml tags (and/or cfscript functions) which generate variables (that CAN be var scoped manually) such as cfhttp, cfsavecontent, cfquery, etc.
Anyway, thanks again, at least it's not leaking!