Udostępnij przez


Przydzielanie i zwalnianie

Wszystkie bufory są przydzielane i zwalniane przez aplikację. Jeśli bufor nie jest odroczony, musi istnieć tylko przez czas trwania wywołania funkcji. Na przykład funkcja SQLGetInfo zwraca wartość skojarzona z określoną opcją w buforze wskazywanym przez argument InfoValuePtr . Ten bufor można zwolnić natychmiast po wywołaniu polecenia SQLGetInfo, jak pokazano w poniższym przykładzie kodu:

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

Ponieważ bufory odroczone są określone w jednej funkcji i używane w innej, jest to błąd w programowaniu aplikacji, aby zwolnić odroczony bufor, podczas gdy sterownik nadal oczekuje jego istnienia. Na przykład adres buforu *ValuePtr jest przekazywany do obiektu SQLBindCol do późniejszego użycia przez narzędzie SQLFetch. Nie można zwolnić tego buforu, dopóki kolumna nie zostanie zwolniona, na przykład z wywołaniem metody SQLBindCol lub SQLFreeStmt , jak pokazano w poniższym przykładzie kodu:

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

Taki błąd można łatwo wykonać, deklarując bufor lokalnie w funkcji; bufor jest zwalniany, gdy aplikacja opuszcza funkcję. Na przykład poniższy kod powoduje niezdefiniowane i prawdopodobnie śmiertelne zachowanie sterownika:

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