VBA私有Long数组元素莫名变为-1的问题求助
VBA私有数组元素莫名显示-1的问题排查
我在支持Excel的项目中实现了包含UDF的模块与类,其中一个类定义了私有Long数组m_FromLastGuess,类初始化时将数组所有元素设为0,仅通过IncrementFromLastGuess方法对数组元素执行递增操作,另有Dump方法将数组内容写入statistics.txt文件。但输出结果显示m_FromLastGuess(0)的值为-1,逻辑上该元素仅能被递增,不可能出现负值。
完整类代码
Option Explicit Private m_FromLastMethodCalls As Long Private m_FromLastBinarySearchMiss As Long Private m_FromLastBinarySearchHit As Long Private m_FromLastBinarySearchAdd As Long Private m_FromLastBinarySearchLastHitIndex As Long Private m_FromLastGuess(2) As Long Private m_FromLastCreateTargetsCollection As Long Private m_FromLastRetrieveCachedTargetsCollection As Long Private m_FromLastError As Long Public Function IncrementFromLastMethodCalls() m_FromLastMethodCalls = m_FromLastMethodCalls + 1 End Function Public Function IncrementFromLastBinarySearchMiss() m_FromLastBinarySearchMiss = m_FromLastBinarySearchMiss + 1 End Function Public Function IncrementFromLastBinarySearchHit() m_FromLastBinarySearchHit = m_FromLastBinarySearchHit + 1 End Function Public Function IncrementFromLastBinarySearchAdd() m_FromLastBinarySearchAdd = m_FromLastBinarySearchAdd + 1 End Function Public Function IncrementFromLastCreateTargetsCollection() m_FromLastCreateTargetsCollection = m_FromLastCreateTargetsCollection + 1 End Function Public Function IncrementFromLastRetrieveCachedTargetCollection() m_FromLastRetrieveCachedTargetsCollection = m_FromLastRetrieveCachedTargetsCollection + 1 End Function Public Function IncrementFromLastError() m_FromLastError = m_FromLastError + 1 End Function Public Property Let lastHitIndex(lastHitIndex As Long) m_FromLastBinarySearchLastHitIndex = lastHitIndex End Property Public Property Get lastHitIndex() As Long lastHitIndex = m_FromLastBinarySearchLastHitIndex End Property Public Function IncrementFromLastGuess(guessNumber As Integer) m_FromLastGuess(guessNumber) = m_FromLastGuess(guessNumber) + 1 End Function Public Function Dump() Open "statistics.txt" For Append As #1 ' Open file for output. Print #1, Format(Now(), "YYYY-MM-DD HH:MM:SS") Print #1, "FromLastMethodCalls: " & Format(Format(m_FromLastMethodCalls, "##,###,##0"), "@@@@@@@@@@") Print #1, "FromLastBinarySearchMiss: " & Format(Format(m_FromLastBinarySearchMiss, "##,###,##0"), "@@@@@@@@@@") Print #1, "FromLastBinarySearchHit: " & Format(Format(m_FromLastBinarySearchHit, "##,###,##0"), "@@@@@@@@@@") Print #1, "FromLastBinarySearchAdd: " & Format(Format(m_FromLastBinarySearchAdd, "##,###,##0"), "@@@@@@@@@@") Print #1, "FromLastGuess(0): " & Format(Format(m_FromLastGuess(0), "##,###,##0"), "@@@@@@@@@@") Print #1, "FromLastGuess(1): " & Format(Format(m_FromLastGuess(1), "##,###,##0"), "@@@@@@@@@@") Print #1, "FromLastGuess(2): " & Format(Format(m_FromLastGuess(2), "##,###,##0"), "@@@@@@@@@@") Print #1, "FromLastError: " & Format(Format(m_FromLastError, "##,###,##0"), "@@@@@@@@@@") Print #1, "FromLastCreateTargetsCollection: " & Format(Format(m_FromLastCreateTargetsCollection, "##,###,##0"), "@@@@@@@@@@") Print #1, "FromLastRetrieveCachedTargetsCollection: " & Format(Format(m_FromLastRetrieveCachedTargetsCollection, "##,###,##0"), "@@@@@@@@@@") Dim total As Long total = m_FromLastError + m_FromLastCreateTargetsCollection + m_FromLastRetrieveCachedTargetsCollection Print #1, "Total: " & Format(Format(total, "##,###,##0"), "@@@@@@@@@@") Close #1 m_FromLastMethodCalls = 0 m_FromLastBinarySearchMiss = 0 m_FromLastBinarySearchHit = 0 m_FromLastBinarySearchAdd = 0 m_FromLastGuess(0) = m_FromLastGuess(1) = m_FromLastGuess(2) = 0 m_FromLastCreateTargetsCollection = 0 m_FromLastRetrieveCachedTargetsCollection = 0 m_FromLastError = 0 End Function Private Sub Class_Initialize() m_FromLastBinarySearchLastHitIndex = -1 m_FromLastGuess(0) = m_FromLastGuess(1) = m_FromLastGuess(2) = 0 End Sub
相关说明
m_FromLastGuess为私有Long类型数组,预期包含3个元素(下标0、1、2)IncrementFromLastGuess是唯一修改该数组的方法,仅执行递增操作- Dump方法中输出数组元素的代码片段:
Print #1, "FromLastGuess(0): " & Format(Format(m_FromLastGuess(0), "##,###,##0"), "@@@@@@@@@@") Print #1, "FromLastGuess(1): " & Format(Format(m_FromLastGuess(1), "##,###,##0"), "@@@@@@@@@@") Print #1, "FromLastGuess(2): " & Format(Format(m_FromLastGuess(2), "##,###,##0"), "@@@@@@@@@@")
输出文件内容
2023-05-26 10:41:54 FromLastMethodCalls: 0 FromLastBinarySearchMiss: 0 FromLastBinarySearchHit: 0 FromLastBinarySearchAdd: 0 FromLastGuess(0): -1 FromLastGuess(1): 10,535 FromLastGuess(2): 856 FromLastError: 0 FromLastCreateTargetsCollection: 0 FromLastRetrieveCachedTargetsCollection: 0 Total: 0
问题根源与解决方法
问题根源:数组下标越界访问
问题出在数组声明与访问逻辑不匹配:
- 数组声明未明确指定下界:类中数组声明为
Private m_FromLastGuess(2) As Long,若类模块中设置了Option Base 1(模块级设置,默认数组下界为1),则该数组实际仅包含2个元素(下标1、2),而非预期的3个。 - 越界访问读取相邻变量:代码中访问
m_FromLastGuess(0)时,因数组无0下标,会越界读取类中前一个成员变量m_FromLastBinarySearchLastHitIndex的值,而该变量在Class_Initialize中被初始化为-1,因此输出结果显示为-1。
验证依据
- 输出中
m_FromLastGuess(1)和m_FromLastGuess(2)的值正常递增,符合数组元素的操作逻辑; m_FromLastGuess(0)的值与m_FromLastBinarySearchLastHitIndex的初始化值完全一致,进一步确认是越界访问导致。
解决方法
- 明确指定数组下界:修改数组声明为
Private m_FromLastGuess(0 To 2) As Long,强制数组下标范围为0-2,不受Option Base设置影响。 - 添加参数合法性校验:在
IncrementFromLastGuess方法中加入参数校验,避免传入非法下标导致越界:
Public Function IncrementFromLastGuess(guessNumber As Integer) ' 校验下标范围 If guessNumber < 0 Or guessNumber > 2 Then Err.Raise vbObjectError + 1001, , "Invalid guessNumber: must be 0, 1, or 2" End If m_FromLastGuess(guessNumber) = m_FromLastGuess(guessNumber) + 1 End Function
内容的提问来源于stack exchange,提问作者mbmast
相关产品推荐
相关产品推荐

