Bagikan melalui


Mengalokasikan dan Membebaskan Buffer

Semua buffer dialokasikan dan dibebaskan oleh aplikasi. Jika buffer tidak ditangguhkan, buffer hanya perlu ada selama panggilan ke fungsi. Misalnya, SQLGetInfo mengembalikan nilai yang terkait dengan opsi tertentu dalam buffer yang ditujukkan oleh argumen InfoValuePtr . Buffer ini dapat dibebaskan segera setelah panggilan ke SQLGetInfo, seperti yang ditunjukkan dalam contoh kode berikut:

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

Karena buffer yang ditangguhkan ditentukan dalam satu fungsi dan digunakan di fungsi lain, itu adalah kesalahan pemrograman aplikasi untuk membebaskan buffer yang ditangguhkan sementara driver masih mengharapkannya ada. Misalnya, alamat buffer *ValuePtr diteruskan ke SQLBindCol untuk digunakan nanti oleh SQLFetch. Buffer ini tidak dapat dibebaskan hingga kolom tidak terikat, seperti dengan panggilan ke SQLBindCol atau SQLFreeStmt seperti yang ditunjukkan dalam contoh kode berikut:

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

Kesalahan seperti itu mudah dilakukan dengan mendeklarasikan buffer secara lokal dalam fungsi; buffer dibebaskan ketika aplikasi meninggalkan fungsi. Misalnya, kode berikut menyebabkan perilaku yang tidak terdefinisi dan mungkin fatal dalam driver:

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