[Gdal-dev] OGR, CPLSPrintf and thread safety

Frank Warmerdam warmerdam at pobox.com
Fri Nov 9 15:05:32 EST 2007


Tamas Szekeres wrote:
> Daniel,
> 
> __declspec(thread) is a Microsoft VC specific so it cannot used as an
> universal solution. Moreover it works in DLLs only when those DLLs are
> bound to the executable, and will not work for those loaded with
> LoadLibrary().
> 
> In this particular case it would be reasonable to allocate the buffer
> in the stack at the beginning of every function using these variables.
> 
> Alternatively there's a fairly platform neutral TLS implementation in
> gdal that can also be used.
> 
> You might want to submit a ticket with this issue.

Folks,

I can confirm that __declspec(thread) is not the "right" solution though
it might do in particular circumstances.  The bug was filed as

   http://trac.osgeo.org/gdal/ticket/1979

I have fixed it in trunk and 1.4 branch by using the CPL*TLS (thread
local storage) services.  I have also made a pass through GDAL in trunk
replacing use of CPLSPrintf() with CPLString which doesn't have the
static buffer and limited buffer size issues of CPLSPrintf().  There are
more places to fix, but I'd like to encourage developers to avoid CPLSPrintf()
in the future, in favor of CPLString.

eg.

This:
   SetLocalCS( CPLSPrintf("\"Panorama\" projection number %d",
                          iProjSys) );

becomes:
   SetLocalCS( CPLString().Printf("\"Panorama\" projection number %d",
                                  iProjSys) );


The CPLString() syntax creates a temporary CPLString object which last
until after the SetLocalCS() function call is completed.  The Printf()
method works normally, and there is a default casting operating for
CPLString to const char *, so SetLocalCS() gets a normal const char *
as it expects.

One thing to be aware of is that the (const char *) casting operator
is only used if the place the CPLString is being passed to is declared
to expect a char * or const char *.  So if you pass CPLString's into
printf() type arguments which are untyped you need to explicitly cast
to const char *, or call the c_str() method.

eg.
         CPLDebug( "OGR_ESRI", "Unsupported projection: %s", osProj.c_str() );

Best regards,
-- 
---------------------------------------+--------------------------------------
I set the clouds in motion - turn up   | Frank Warmerdam, warmerdam at pobox.com
light and sound - activate the windows | http://pobox.com/~warmerdam
and watch the world go round - Rush    | President OSGeo, http://osgeo.org




More information about the gdal-dev mailing list