Opened 2 months ago

Closed 2 months ago

Last modified 2 months ago

#7254 closed defect (fixed)

CPLString makes gdal.dll export symbols for std::string on MSVS 2010-2017

Reported by: opals Owned by: warmerdam
Priority: normal Milestone: 2.3.0
Component: default Version: 2.2.3
Severity: normal Keywords: CPLString multiply defined symbols STL
Cc:

Description

Because CPLString derives from std::string, gdal.dll created with MSVC (tested on MSVS 2010 and MSVS 2017) exports symbols not only for CPLString, but also for std::string. This becomes a problem when linking both GDAL and a static library that (implicitly) instantiates std::string (many will do that!). The work-around to force the linker to still generate its output is a generally unsafe option. Much better is to make CPLString not export symbols for std::string. This relates to the same problem as defect #4099 However, in #4099, we suggested to either

  • not export symbols for CPLString at all, which forces binaries that need to use CPLString (like the GDAL utility programs) to link GDAL statically, or
  • not derive CPLString from std::string, but make std::string a member variable hidden in a D-Pointer (pimpl-idiom).

Contrary to the 2 options suggested in #4099, we now use a much less intrusive solution: For MSVC, turn the declaration of CPLString into the declaration of the template class CPLStringT, and make CPLString itself a typedef of that template class. Do not export symbols for the template class as a whole, but only for its few non-inline member functions. Hence, no symbols for std::string are exported, and no symbols for the inline member functions of CPLString. Still, all methods of CPLString and its base class std::string remain available, since they are implicitly instantiated (instead of explicitly, like currently), thereby avoiding duplicate symbols. Resolution attached, based on GDAL 2.2.3. Possibly, also port/cpl_port.h needs to be extended slightly, such that CPL_DLL is defined as declspec(dllimport) when symbols are to be imported by MSVC:

#ifndef CPL_DLL #if defined(_MSC_VER) && !defined(CPL_DISABLE_DLL) # ifdef GDAL_EXPORTS # define CPL_DLL declspec(dllexport) # else # define CPL_DLL declspec(dllimport) # endif #else ... #endif

Attachments (3)

cpl_port.h (43.8 KB) - added by opals 2 months ago.
cpl_port.h Based on GDAL 2.2.3
cpl_string.h (22.6 KB) - added by opals 2 months ago.
cpl_string.h based on GDAL 2.2.3
cplstring.cpp (15.4 KB) - added by opals 2 months ago.
cplstring.cpp based on GDAL 2.2.3

Download all attachments as: .zip

Change History (7)

Changed 2 months ago by opals

Attachment: cpl_port.h added

cpl_port.h Based on GDAL 2.2.3

Changed 2 months ago by opals

Attachment: cpl_string.h added

cpl_string.h based on GDAL 2.2.3

Changed 2 months ago by opals

Attachment: cplstring.cpp added

cplstring.cpp based on GDAL 2.2.3

comment:1 Changed 2 months ago by Even Rouault

@opals Can you propose your changes as a pull request against https://github.com/OSGeo/gdal so that it is easier to review them ?

comment:2 Changed 2 months ago by opals

Pull request submitted: opalsTUW:opalsTUW-no-std-string-symbols

comment:3 Changed 2 months ago by Even Rouault

Resolution: fixed
Status: newclosed

In 41795:

CPLString: avoid std::string symbols to be exported with Visual Studio (patch by opals, fixes #7254, fixes https://github.com/OSGeo/gdal/pull/321)

comment:4 Changed 2 months ago by Even Rouault

Milestone: 2.3.0

I considered to backport this for 2.2.4 as well, but it looks like it would change the ABI, so I decided not.

Note: See TracTickets for help on using tickets.