[freetds] ENOMEM vs. errno

Christos Zoulas christos at zoulas.com
Thu Dec 6 13:15:27 EST 2007


On Dec 6,  7:04pm, freddy77 at gmail.com (Frediano Ziglio) wrote:
-- Subject: Re: [freetds] ENOMEM vs. errno

| 
| Il giorno gio, 06/12/2007 alle 12.06 -0500, James K. Lowden ha scritto:
| > Hi Freddy, 
| > 
| > I'm surprised by 
| > 
| >      $Id: dblib.c,v 1.312 2007/12/06 07:52:17 freddy77 Exp $
| > 
| > which replaces all  
| > 	dbperror(dbproc, SYBEMEM, errno); 
| > with 
| > 	dbperror(dbproc, SYBEMEM, ENOMEM);
| > 
| > Was yesterday's discussion unclear?  
| > 
| > If malloc fails, it must set errno to ENOMEM.  
| > 
| > If malloc does not set errno to ENOMEM, the application should deal with
| > it.  
| > 
| > db-lib's job in this case is only to convey what malloc(3) said.  If
| > malloc returned NULL and didn't set errno to ENOMEM, that's not db-lib's
| > problem.  That's for the application to settle with malloc(3).  If the
| > application cannot rely on malloc to set errno, it has enough information
| > from SYBEMEM.  
| > 
| > By hard-coding ENOMEM, you are hiding what actually happened, potentially
| > lying to the application.  
| > 
| > Remember the application is written in C, too, and uses malloc all the
| > time. It knows how to recognize malloc failures.  Win32 even has
| > _set_new_mode() to control how allocation errors are handled.  I think it
| > sets errno by default.  (The docs don't say so, but they do list ENOMEM as
| > one of the supported errno values.)  
| > 
| > Would you kindly revert to 1.311?  
| > 
| > Thanks.  If I'm overlooking something, just say so.  
| > 
| > Regards, 
| > 
| > --jkl
| > 
| 
| I compiled this program with MingW
| 
| #include <stdio.h>
| #include <stdlib.h>
| 
| int main()
| {
|         void *p1, *p2, *p3;
|         p1 = malloc(0x20000000u);
|         p2 = malloc(0x20000000u);
|         errno = 123;
|         p3 = malloc(0x20000000u);
|         printf("%p %p %p %d\n", p1, p2, p3, errno);
|         return 0;
| }
| 
| And it output
| 
| 00540020 00000000 00000000 123
| 
| :(
| 
| MingW use the "old" msvcrt.dll (Visual C++ 2005 use a new version). As
| Chistos says malloc can set errno only to ENOMEM so I think that
| replacing errno with ENOMEM at the end just remove a problem with
| no-compliant (and existing) malloc implementations.
| 
| Another way to fix this issue would be to have somthing like
| 
| #ifdef WIN32
|    /* fix errno setting in some windows malloc implementations */
|    if (msgno == SYBEMEM)
|       errnum = ENOMEM;
| #endif
| 
| Would you prefer this change? 

I think it is less intrusive and also documents what's broken and
how you are working around it. I would say in the comment:

/*
 * Unfortunately MingW uses the "old" msvcrt.dll (Visual C++ 2005 uses
 * a newer version) which does not set errno when allocation functions
 * cannot allocate memory, so we do it for them.
 */

christos


More information about the FreeTDS mailing list