14 October 2009

The Sub-ByRef flaw

A call to a Sub procedure using by reference arguments might not update the correct variable. To understand this behavior be sure to understand the differences between ByVal and ByRef arguments. This is explained in the next tip 'Passing values ByRef or ByVal'. Here you have learned that a Sub by default takes arguments as ByRef, making ByRef optional. Unfortunately this is not always true.

When an argument is passed by reference, the procedure is passed the address of the argument variable. When the argument is a global variable the address of the variable is passed as expected. In the following situation the ByRef clause is omitted and the global variable is updated to 100 correctly.

Global a% = 50
MySub(a%)
Print a%   ' 100
Sub MySub(b%)
  b% = 100
EndSub

When a second Sub is called from within MySub passing b% by reference, b% is  not updated as expected. The variable b% is passed by value, rather than by reference!

Sub MySub(b%)
  b% = 100 : NextSub(b%) : Print b%  // still 100
EndSub
Sub NextSub(c%)
  c% = 200    // unexpected: c% is ByVal argument
EndSub

Why this is happening is unclear, but it is easily repaired by using ByRef explicitly in Sub headings.

Sub NextSub(ByRef c%)

No comments:

Post a Comment