所以我在生产中遇到了一个问题,似乎是通过Service Pack升级暴露出来的。它似乎是ado _ConnectionPtr对象的Execute方法中的某种缓冲区溢出。以下代码产生缓冲区溢出:
char szStatement[600];
sprintf(szStatement, "UPDATE ROUTING_MASTER SET CNTNR_WGT_EST = %g WHERE CNTNR_ID = '%s'",
spLineItem->CntnrItemsWeight, (LPCTSTR) spLineItem->ContainerID);
m_spCN->Execute(szStatement,&var,adCmdText);
在execute方法之后,它会遍历我的一个成员变量(_bstr_t),下次应用程序尝试访问被践踏的成员变量时,它会抛出异常。我可以告诉它被践踏,因为我在监视窗口中有我的成员变量,并且在Execute方法完成后立即看到成员变量已经改变(m_bstrDate):
var在头文件中声明为:
variant_t var;
BOOL m_bUseStorePutCntnr;
_bstr_t m_bstrDate, m_bstrTime;
似乎对& var的赋值正是这样做的,因为如果我将其更改为以下内容则不会践踏我的成员变量:
m_spCN->Execute(szStatement, NULL, adCmdText);
我不确定这是否与Service Pack有关,因为我在我的开发环境中也看到了这一点,而visual studio在下次必须访问该成员变量时会继续运行。
知道为什么会导致缓冲区溢出?
答案 0 :(得分:0)
我没有使用ADO环境设置的Visual C / C ++ v6.0,因此我无法验证下面写的任何内容。
但很明显,使用Execute
方法的第二个参数传递的保留内存块的地址不够大。
我在MSDN中找不到类_ConnectionPtr
,也没有找到此类的方法Execute
。但我找到了页面ADO interface _ConnectionPtr。根据此页面,方法Execute
的原型是:
_RecordsetPtr Connection :: Execute (_bstr_t CommandText, VARIANT * RecordsAffected, long Options)
所以第二个参数是指向结构VARIANT的指针。
但是您已将成员变量var
定义为类variant_t的对象,该对象封装了 VARIANT 结构。
我100%认为结构 VARIANT 的大小与类 variant_t 的大小不同。
您应该可以通过插入代码来验证:
TRACE("Size of VARIANT is %u and size of variant_t is %u\n",sizeof(VARIANT),sizeof(variant_t));
我的结论:
您将错误的对象传递给方法Execute
!
您的应用程序应该可以使用 VARIANT 替换头文件 variant_t ,并且可能使用
清除结构的所有字节memset(&var,0,sizeof(var));
在调用方法Execute
之前,虽然我非常确定这不是真的需要。
如果您想另外使用 variant_t 类,您还必须定义 VARIANT 结构并将其附加到 variant_t 对象。< / p>
这意味着你需要在头文件中:
VARIANT var;
variant_t RecordsAffected;
在源文件中:
memset(&var,0,sizeof(var)); // Most likely not really needed.
m_spCN->Execute(szStatement,&var,adCmdText);
RecordsAffected.Attach(&var);
如果我在代码片段上犯了错误,请告诉我,我根本无法测试,以及我的答案中的任何其他错误信息。