CFMX 6.1 versus CFMX 7: War of the Arrays

Arrays in 6.1 are passed differently than in CFMX 7. I know this to be true.

What does that mean?

There are at least two ways to pass the contents of a memory address. Let's look at each:

Pass By Value:

This is the easiest to understand. What this means is the value of the memory address is returned. Any alterations do not affect the original value.

Pass By Reference:

This is a little trickier. Passing by reference means that a reference to the original value is handed off. Any changes to the value will be reflected in the original value.

Enough with the abstract; lets look at some code.

Here is an example of pass by value:

view plain print about
1<cfset foo = 5 />
2 <cfset doFoo( foo ) />
3 <cffunction name="doFoo" returntype="void">
4 <cfargument name="foo" />
5 <cfset foo = foo + 1 />
6 <!--- Foo is 6 right here --->
7 <cfdump var="#foo#" />
8 </cffunction>
9 <!--- foo is 5 here --->
10 <cfdump var="#foo#" />

Here is an example of pass by reference

view plain print about
1<cfset fooStruct = structNew() />
2 <cfset fooStruct['bar'] = 'baz' />
3 <cfset doFoo( fooStruct ) />
4 <cffunction name="doFoo" returntype="void">
5 <cfargument name="foo" />
6 <cfset foo['bar'] = 'nuts' />
7 <!--- foo contains nuts here --->
8 <cfdump var="#foo#" />
9 </cffunction>
10 <!--- foo still contains nuts here --->
11 <cfdump var="#foo#" />

Thus illustrates pass by reference and pass by value. If you noted, I used a simple value, a numerical value for the pass by reference and for the pass by value example, I used a struct. In coldfusion, the general rule of thumb is simple values (strings, numbers) are passed by value and complex values (structs, objects) are passed by reference.

While developing an application recently, I noted an irregularity between CFMX 6.1 and CFMX 7 as to how values are passed. I personally consider Arrays to be complex values. If you have ever unknowingly passed an array into a CF Function that was expecting a simple value, you can see that ColdFusion agrees with me.

I was passing an array into a function in order to determine the filtering criteria on a query based on a user roles. Since the array was created within the scope of the original function and then passed into the inner function, on CFMX 6.1 the array was passed by reference. The filtering criteria were set into the array.

During testing, our testers marked a bug for this functionality. "This function returns too many records", they said.

Dutifully, I would test the process on my development machine running MX 6.1 (identical as our production environment) and it worked flawlessly.

Getting closer to our rollout, we began to get nervous about the disparity. Some bugs just couldn't stay closed.

After researching the problem our development group figured out the source of the problem. Seems our testers were using a CFMX 7 environment for testing. Our production environment was CFMX 6.1 (Yeah, don't even say it. I already know. It will probably be a blog post at some point. )

Seems in 6.1, as the array was passed by reference, the values inside were changed and were a part of the original array. When unwound for the filtering criteria, the correct data sets cut the query properly.

In CFMX 7, the array was passed by value. What this means is the array was COPIED into the function, where new values were added, and then it died. The original array was unchanged, thus no filtering criteria was available to cut the query.

It took us a few hours of thinking on this to figure out it was the application behaving differently on each environment.

There was a lot of this:

view plain print about
1Dev 1: Are you sure you moved the right code?
2Dev 2: I dunno, Lets diff the code and make sure.
3
4Then 15 minutes later....
5
6Dev 1: Are you sure you moved the right code?

There is a very nice write-up at Mark Mandel's blog about this very issue. Be sure to read into the comments for extra insight as to why this problem existed.

There are no comments for this entry.

Add Comment Subscribe to Comments