Search code examples
vbscriptasp-classic

inexplicable crash fixed by superfluous assignment


I was testing a tiny snippet I'd written to format a timespan (e.g., last change 5m23s ago) and kept getting an error I couldn't understand. Every time I try to use the loop variable i directly in a call to ts(), ASP informed me An error occurred...

'the function
function ts(s)
    dim m: m = CLng(s \ 60): s = s mod 60
    dim h: h = CLng(m \ 60): m = m mod 60
    ts = right("00" & h, 2) & "h" & _
         right("00" & m, 2) & "m" & _
         right("00" & s, 2) & "s" 
end function 

'the test
for i = 0 to 90000 step 15 
   '               response.write i & ": " & ts(i) & "<br />" 'an error has occurred
    dim j: j = i : response.write i & ": " & ts(j) & "<br />" 'works fine
next 

What in the world is going on here?

Why does ts(i) create an error every time?
Given that, why does j=i : ts(j) work fine?

It can't be a problem with the variable i, since it works fine with the write call. Here's some other things I tried:

response.write i & ": "                     'no problem
'response.write ts(i)                       'crashes
'dim x: x = ts(i)                           'crashes
dim j: j = i                                'no problem
dim x: x = ts(j)                            'works
response.write x & "<br />"                 'works 
'response.write ts(j) & "<br />"            'also works 
'response.write i & ": " & ts(j) & "<br />" 'also works 

(Finally, I know there's allegedly a way to make IIS display real errors. I'd love to hear how to do that without RDP access to the webserver.)


Solution

  • omegastripes clued me in.

    Apparently in VBScript, the default is for parameters to be passed ByReference.
    (Literally every other programming language I've ever used passes primitives ByValue)

    This caused a problem when I changed the value of s inside the function.

    Any of these snippets work just fine:

    function ts(ByVal s)
        ...
    ...
    ts(i)
    
    function ts(sec)
        dim s: s = sec
        ...
    ...
    ts(i)
    

    (or, as mentioned in the OP, passing the value in a non-loop-iterator variable)

    function ts(s) 
    ... 
    dim j: j = i: ts(j)