在VC中使用ADO碰到的一个返回值溢出问题

        在最近的一个项目中, 使用ADO访问数据库,在获取存储过程的RETURN返回值时,发现一个奇怪的现象。在SQL查询分析器中运行时获得的RETRUN值竟然与应用程序中返回值出现不一致情况。经过多次验证发现,只要RETURN的值超过32767,应用程序获得的值就是负数。看样子是溢出了。

        由于程序中使用的数据库类是从Codeguru上找的,只好去分析一下其中的原因。经过分析发现,该程序使用函数

BOOL CADOParameter::GetValue( int &  nValue)
{
    _variant_t vtVal;
    
int nVal = 0;

    
try
    
{
        vtVal 
= m_pParameter->Value;

        
switch(vtVal.vt)
        
{
        
case VT_I4:
            nVal 
= vtVal.lVal;
            
break;
        
case VT_BOOL:
            nVal 
= vtVal.boolVal;
            
break;
        
case VT_I2:
        
case VT_UI1:
            nVal 
= vtVal.iVal;
            
break;
        
case VT_INT:
            nVal 
= vtVal.intVal;
            
break;        
        
case VT_NULL:
        
case VT_EMPTY:
            nVal 
= 0;
            
break;
        
default:
            nVal 
= vtVal.iVal;
        }
    
        nValue 
= nVal;
        
return TRUE;
    }

    
catch(_com_error& e)
    
{
        dump_com_error(e);
        
return FALSE;
    }

}

来获得int型的返回值。在获取返回值前,利用事先定义的保存返回值的参数的类型来判断获取vtVal的哪个值。

输入参数定义为

CADOParameter pParam_PreDoPreserveRetVal(CADORecordset::typeInteger,  sizeof ( int ), CADOParameter::paramReturnValue);

也即这个RETURN值为int型的。但是,在调试上面的那个GetValue的值中,vtVal.vt的值为3,下面的case选项中没有对应的值。于是就调用了default分支。查看了一下vtVal.vt的定义,定义如下:

 

enum  VARENUM
    
{    VT_EMPTY    = 0,
    VT_NULL    
= 1,
    VT_I2    
= 2,
    VT_I4    
= 3,
    VT_R4    
= 4,
    VT_R8    
= 5,
    VT_CY    
= 6,
    VT_DATE    
= 7,
    VT_BSTR    
= 8,
    VT_DISPATCH    
= 9,
    VT_ERROR    
= 10,
    VT_BOOL    
= 11,
    VT_VARIANT    
= 12,
    VT_UNKNOWN    
= 13,
    VT_DECIMAL    
= 14,
    VT_I1    
= 16,
    VT_UI1    
= 17,
    VT_UI2    
= 18,
    VT_UI4    
= 19,
    VT_I8    
= 20,
    VT_UI8    
= 21,
    VT_INT    
= 22,
    VT_UINT    
= 23,
    VT_VOID    
= 24,
    VT_HRESULT    
= 25,
    VT_PTR    
= 26,
    VT_SAFEARRAY    
= 27,
    VT_CARRAY    
= 28,
    VT_USERDEFINED    
= 29,
    VT_LPSTR    
= 30,
    VT_LPWSTR    
= 31,
    VT_RECORD    
= 36,
    VT_INT_PTR    
= 37,
    VT_UINT_PTR    
= 38,
    VT_FILETIME    
= 64,
    VT_BLOB    
= 65,
    VT_STREAM    
= 66,
    VT_STORAGE    
= 67,
    VT_STREAMED_OBJECT    
= 68,
    VT_STORED_OBJECT    
= 69,
    VT_BLOB_OBJECT    
= 70,
    VT_CF    
= 71,
    VT_CLSID    
= 72,
    VT_VERSIONED_STREAM    
= 73,
    VT_BSTR_BLOB    
= 0xfff,
    VT_VECTOR    
= 0x1000,
    VT_ARRAY    
= 0x2000,
    VT_BYREF    
= 0x4000,
    VT_RESERVED    
= 0x8000,
    VT_ILLEGAL    
= 0xffff,
    VT_ILLEGALMASKED    
= 0xfff,
    VT_TYPEMASK    
= 0xfff
    }
 ;

VT_I4 = 3。而VT_I4   正好是 4 byte signed int。看来是GetValue有问题。于是增加了这个分支,将其与VT_INT合并。以下位值的枚举:

 

LONGLONG llVal;
                LONG lVal;
                BYTE bVal;
                SHORT iVal;
                FLOAT fltVal;
                DOUBLE dblVal;
                VARIANT_BOOL boolVal;
                _VARIANT_BOOL 
bool ;
                SCODE scode;
                CY cyVal;
                DATE date;
                BSTR bstrVal;
                IUnknown 
* punkVal;
                IDispatch 
* pdispVal;
                SAFEARRAY 
* parray;
                BYTE 
* pbVal;
                SHORT 
* piVal;
                LONG 
* plVal;
                LONGLONG 
* pllVal;
                FLOAT 
* pfltVal;
                DOUBLE 
* pdblVal;
                VARIANT_BOOL 
* pboolVal;
                _VARIANT_BOOL 
* pbool;
                SCODE 
* pscode;
                CY 
* pcyVal;
                DATE 
* pdate;
                BSTR 
* pbstrVal;
                IUnknown 
** ppunkVal;
                IDispatch 
** ppdispVal;
                SAFEARRAY 
** pparray;
                VARIANT 
* pvarVal;
                PVOID byref;
                CHAR cVal;
                USHORT uiVal;
                ULONG ulVal;
                ULONGLONG ullVal;
                INT intVal;
                UINT uintVal;
                DECIMAL 
* pdecVal;
                CHAR 
* pcVal;
                USHORT 
* puiVal;
                ULONG 
* pulVal;
                ULONGLONG 
* pullVal;
                INT 
* pintVal;
                UINT 
* puintVal;

 

 

 

你可能感兴趣的:(在VC中使用ADO碰到的一个返回值溢出问题)