Looping array frequently goes out of bounds
Hello all,
I have a process which pulls information from a database, converts the data into an array, in which every element contains a structure with two keys (name and value). That information is then processed and returned to another system. The problem is, often times when looping over the array that contains the structures, the loop will go out of bounds and attempt to access array elements that do not exist. Further more, sometimes either the "name" or "value" key will be blank. I currently am unaware of any pattern to this behavior.
<!--- Get all the data for the given PID (an ID number associated to a contact) --->
<cfquery name="Login" datasource="WebServer" maxrows="1">
Select *
From SFContactSync
Where PID = <cfqueryparam cfsqltype="cf_sql_integer" value="#form.PID#">
</cfquery>
<!--- Assign All the information from the login query into variables we can return --->
<cfloop list="#Login.columnList#" index="columnName">
<cfset counter = counter + 1>
<cfset VariablesObject[counter] = structnew()>
<cfset VariablesObject[counter]["Name"] = columnName>
<cfset VariablesObject[counter]["Value"] = #Login[columnName][1]#>
</cfloop>
<!--- Create one more entry that contains the full name of the person --->
<cfset counter = counter + 1>
<cfset VariablesObject[counter] = structnew()>
<cfset VariablesObject[counter]["Name"] = "FullName">
<cfset VariablesObject[counter]["Value"] = "#Login.Firstname# #Login.Lastname#">
<!--- Set the next page to go to --->
<cfset nextPage = "/15">
<cfset ReturnObject = server.IVRUtilities.printMessage(nextPage,VariablesObject)>
<!--- Function for creating return AngelXML --->
<cffunction name="printMessage" access="remote" hint="Print a message for the Angel IVR System">
<cfargument name="address" default="none" type="string">
<!--- This is an array of structures, with keys "name" and "value" --->
<!--- EX variables[1].Name = Gender --->
<!--- EX variables[1].Value = Male --->
<cfargument name="variablesToInclude" default="" type="any" required="no">
<cfargument name="promptText" default="." type="string" required="no">
<cfoutput>
<cfsavecontent variable="ReturnMessage">
<ANGELXML>
<MESSAGE>
<PLAY>
<PROMPT type="text">
<cfoutput>#arguments.promptText#</cfoutput>
</PROMPT>
</PLAY>
<GOTO destination="#listlast(address)#" />
</MESSAGE>
<cfif IsArray(arguments.variablesToInclude)>
<VARIABLES>
<cftry>
<cfloop from="1" to="#arraylen(arguments.variablesToInclude)#" index="i">
<cfif structkeyexists(arguments.variablesToInclude,'Name') and structkeyexists(arguments.variablesToInclude,'value')>
<VAR name="#ucase(arguments.variablesToInclude['Name'])#" value="#ucase(arguments.variablesToInclude['Value'])#" />
</cfif>
</cfloop>
<cfcatch type="any">
<cfset ErrorData = structnew()>
<cfset ErrorData.Error = cfcatch>
<cfset ErrorData.Arguments = arguments>
<cfset ErrorData.form = form>
<cfset SendError = server.utilities.SendErrorReport(ErrorData)>
</cfcatch>
</cftry>
</VARIABLES>
</cfif>
</ANGELXML>
</cfsavecontent>
</cfoutput>
<cfreturn ReturnMessage>
</cffunction>
For example, I have an error sitting in my inbox now that says
The element at position 25 cannot be found.
But viewing the dump of the included elements shows only 24 elements. For some reason the loop here
<cfloop from="1" to="#arraylen(arguments.variablesToInclude)#" index="i">
<cfif structkeyexists(arguments.variablesToInclude,'Name') and structkeyexists(arguments.variablesToInclude,'value')>
<VAR name="#ucase(arguments.variablesToInclude['Name'])#" value="#ucase(arguments.variablesToInclude['Value'])#" />
</cfif>
</cfloop>
does seem to stop at the right point. The cfif statment would error, becuase it tries to evaluate an array element that does not exist. Whats up with that?
I was thinking of adding more checking to see if the array element exsists, but I am hesitant to add any more "checking" code than I really need beucase this is a somewhat high performance critical app. Any thoughts or comments are welcome.
