D. Richard Hipp wrote:

On Wed, 2005-06-29 at 15:19 +0300, Lauri Nurmi wrote:
So, basically, is there a reason why sqlite3Malloc(n) & co should even
try to allocate zero bytes, instead of just returning NULL if n==0? Does
a pointer pointing to zero bytes of memory have any use anyway?


Yes.  A NULL return from sqlite3Malloc() is an error condition meaning
that you have run out of memory.  That is very different from returning
a zero-length memory allocation.
Richard,

I don' t believe that this is true. In the source for sqlite3Malloc() you do an explicit check for a requested size of 0 and return zero without calling the library malloc function. So you will return NULL for this case even if there is plenty of memory left. A NULL return does not mean out of memory.

The code of concern is in sqlite3_exec where you allocate zero bytes for a statement that has no result columns. Here you follow the allocation with an explicit check that the number of requested bytes was non-zero AND the allocated memory pointer is NULL before you declare an out of memory error.

This code appears to be safe since the azCol buffer is only referenced if the number of result columns is greater than zero (except where it is released, but freeing a NULL pointer is supposed to be safe, though there are systems where this can be problematic), so the allocation should always be valid or correctly generate an out of memory error.

It might be clearer to separate the check for the number of result columns and only do the allocation if it is greater than 0. This will leave the azCol pointer with its initialized value of 0 if there are no results. You could replace:

   azCols = sqliteMalloc(2*nCol*sizeof(const char *));
   if( nCol && !azCols ){
     rc = SQLITE_NOMEM;
     goto exec_out;
   }

with

   if( nCol > 0 ){
       azCols = sqliteMalloc(2*nCol*sizeof(const char *));
       if( !azCols ){
           rc = SQLITE_NOMEM;
           goto exec_out;
       }
   }

This would save a subroutine call and the checks in sqlite3Malloc for the common case of users using sqlite3_exec() for statments such as "BEGIN TRANSACTION". Admittedly, this is a very small performance gain.

Dennis Cote

Reply via email to