Dela via


Allokera och frigöra buffertar

Alla buffertar allokeras och frigörs av programmet. Om en buffert inte skjuts upp, behöver den bara finnas under det tidsintervall en funktion anropas. Till exempel returnerar SQLGetInfo värdet som är associerat med ett visst alternativ i bufferten som pekar på av argumentet InfoValuePtr . Den här bufferten kan frigöras omedelbart efter anropet till SQLGetInfo, enligt följande kodexempel:

SQLSMALLINT   InfoValueLen;  
SQLCHAR *     InfoValuePtr = malloc(50);   // Allocate InfoValuePtr.  
  
SQLGetInfo(hdbc, SQL_DBMS_NAME, (SQLPOINTER)InfoValuePtr, 50,  
            &InfoValueLen);  
  
free(InfoValuePtr);                        // OK to free InfoValuePtr.  

Eftersom uppskjutna buffertar anges i en funktion och används i en annan är det ett programprogrammeringsfel som frigör en uppskjuten buffert medan drivrutinen fortfarande förväntar sig att den ska finnas. Till exempel skickas adressen för *ValuePtr-bufferten till SQLBindCol för senare användning av SQLFetch. Det går inte att frigöra den här bufferten förrän kolumnen är obundet, till exempel med ett anrop till SQLBindCol eller SQLFreeStmt enligt följande kodexempel:

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);  

Ett sådant fel görs enkelt genom att bufferten deklareras lokalt i en funktion. bufferten frigörs när programmet lämnar funktionen. Följande kod orsakar till exempel odefinierat och förmodligen dödligt beteende i drivrutinen:

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.  
}