分配和释放缓冲区
所有缓冲区均由应用程序分配和释放。 如果缓冲区未延迟,则只需在函数调用期间存在缓冲区。 例如,SQLGetInfo 返回与 InfoValuePtr 参数指向的缓冲区中的特定选项关联的值。 调用 SQLGetInfo 后,可以立即释放此缓冲区,如以下代码示例所示:
SQLSMALLINT InfoValueLen;
SQLCHAR * InfoValuePtr = malloc(50); // Allocate InfoValuePtr.
SQLGetInfo(hdbc, SQL_DBMS_NAME, (SQLPOINTER)InfoValuePtr, 50,
&InfoValueLen);
free(InfoValuePtr); // OK to free InfoValuePtr.
由于延迟缓冲区在一个函数中指定并在另一个函数中使用,因此在驱动程序仍预期延迟缓冲区存在时释放延迟缓冲区是应用程序编程错误。 例如,*ValuePtr 缓冲区的地址将传递到 SQLBindCol,供 SQLFetch 稍后使用。 在列未绑定之前,无法释放此缓冲区(例如通过调用 SQLBindCol 或 SQLFreeStmt),如以下代码示例所示:
SQLRETURN rc;
SQLINTEGER ValueLenOrInd;
SQLHSTMT hstmt;
// Allocate ValuePtr
SQLCHAR * ValuePtr = malloc(50);
// Bind ValuePtr to column 1. It is an error to free ValuePtr here.
SQLBindCol(hstmt, 1, SQL_C_CHAR, ValuePtr, 50, &ValueLenOrInd);
// Fetch each row of data and place the value for column 1 in *ValuePtr.
// Code to check if rc equals SQL_ERROR or SQL_SUCCESS_WITH_INFO
// not shown.
while ((rc = SQLFetch(hstmt)) != SQL_NO_DATA) {
// It is an error to free ValuePtr here.
}
// Unbind ValuePtr from column 1. It is now OK to free ValuePtr.
SQLFreeStmt(hstmt, SQL_UNBIND);
free(ValuePtr);
通过在函数中本地声明缓冲区,很容易发生此类错误;当应用程序离开函数时,缓冲区将释放。 例如,以下代码会导致驱动程序中出现未定义且可能致命的行为:
SQLRETURN rc;
SQLHSTMT hstmt;
BindAColumn(hstmt);
// Fetch each row of data and try to place the value for column 1 in
// *ValuePtr. Because ValuePtr has been freed, the behavior is undefined
// and probably fatal. Code to check if rc equals SQL_ERROR or
// SQL_SUCCESS_WITH_INFO not shown.
while ((rc = SQLFetch(hstmt)) != SQL_NO_DATA) {}
.
.
.
void BindAColumn(SQLHSTMT hstmt) // WARNING! This function won't work!
{
// Declare ValuePtr locally.
SQLCHAR ValuePtr[50];
SQLINTEGER ValueLenOrInd;
// Bind rgbValue to column.
SQLBindCol(hstmt, 1, SQL_C_CHAR, ValuePtr, sizeof(ValuePtr),
&ValueLenOrInd);
// ValuePtr is freed when BindAColumn exits.
}