有生就有死,既然有了singleton对象GDALDriverManger,就要在main函数退出之前销毁它。
前文GDAL singleton的经典错误 已经分析了这是DCLP的模式,最后由一个指针poDM指向被创建出来的唯一的对象。因为是new出来的,自然要找到delete的地方。同样在gdaldrivermanager.cpp文件,在最后的位置,提供了函数GDALDestroyDriverManager用来完成最后的清理工作。 注释提醒,不要在其他线程还在使用GDAL内部的对象时调用该函数。我只会在退出前调用。
/**
* \brief Destroy the driver manager.
*
* Incidently unloads all managed drivers.
*
* NOTE: This function is not thread safe. It should not be called while
* other threads are actively using GDAL.
*/
void CPL_STDCALL GDALDestroyDriverManager( void )
{
// THREADSAFETY: We would like to lock the mutex here, but it
// needs to be reacquired within the destructor during driver
// deregistration.
if( poDM != NULL )
delete poDM;
}
poDM也定义在这个文件开头,是一个静态指针。
static volatile GDALDriverManager *poDM = NULL;
/************************************************************************/
/* ~GDALDriverManager() */
/* */
/* Eventually this should also likely clean up all open */
/* datasets. Or perhaps the drivers that own them should do */
/* that in their destructor? */
/************************************************************************/
GDALDriverManager::~GDALDriverManager()
{
/* -------------------------------------------------------------------- */
/* Destroy the existing drivers. */
/* -------------------------------------------------------------------- */
while( GetDriverCount() > 0 )
{
GDALDriver *poDriver = GetDriver(0);
DeregisterDriver(poDriver);
delete poDriver;
}
m_NameDriverMap.clear();
/* -------------------------------------------------------------------- */
/* Cleanup local memory. */
/* -------------------------------------------------------------------- */
VSIFree( papoDrivers );
VSIFree( pszHome );
/* -------------------------------------------------------------------- */
/* Cleanup any Proxy related memory. */
/* -------------------------------------------------------------------- */
PamCleanProxyDB();
/* -------------------------------------------------------------------- */
/* Blow away all the finder hints paths. We really shouldn't */
/* be doing all of them, but it is currently hard to keep track */
/* of those that actually belong to us. */
/* -------------------------------------------------------------------- */
CPLFinderClean();
CPLFreeConfig();
/* -------------------------------------------------------------------- */
/* Cleanup any memory allocated by the OGRSpatialReference */
/* related subsystem. */
/* -------------------------------------------------------------------- */
OSRCleanup();
/* -------------------------------------------------------------------- */
/* Cleanup VSIFileManager. */
/* -------------------------------------------------------------------- */
VSICleanupFileManager();
/* -------------------------------------------------------------------- */
/* Cleanup thread local storage ... I hope the program is all */
/* done with GDAL/OGR! */
/* -------------------------------------------------------------------- */
CPLCleanupTLS();
/* -------------------------------------------------------------------- */
/* Ensure the global driver manager pointer is NULLed out. */
/* -------------------------------------------------------------------- */
if( poDM == this )
poDM = NULL;
}
这个析构函数的注释很奇怪,居然提问,是不是应该让driver的析构函数负责清理工作。当然应该这样。这也带来个疑问,这些driver的析构函数还是有必要看一下。
如果看官方API Reference文档,只能看到公有成员的描述,所以如果想把握GDAL内部的运行原理,只有看代码是唯一的有效方式。
http://www.gdal.org/classGDALDriverManager.html
delete poDriver会导致GDALDriver析构函数被调用,
GDALDriver::~GDALDriver()
{
if( pfnUnloadDriver != NULL )
pfnUnloadDriver( this );
}这个GDALDriver没有采用常规的C++多态方式,即不同的driver用不同子类来实现,而是用了函数指针的方式。典型C风格!
如果是GeoTiff驱动时,会调用到geotiff.cpp文件的函数:
/************************************************************************/
/* GDALDeregister_GTiff() */
/************************************************************************/
void GDALDeregister_GTiff( GDALDriver * )
{
CPLDebug( "GDAL", "GDALDeregister_GTiff() called." );
CSVDeaccess( NULL );
#if defined(LIBGEOTIFF_VERSION) && LIBGEOTIFF_VERSION > 1150
GTIFDeaccessCSV();
#endif
}
void GTIFDeaccessCSV()
{
CSVDeaccess( NULL );
}
结果追踪下来,driver没有什么有效代码做清理。除了GDALDriver的析构函数做了默认的清理以外。
获许因为没什么东西真的不需要清理,或许是bug。暂时还说不准,我只是对这种用C函数指针代替虚函数的设计究竟能带来多少好处,表示怀疑。
本文探讨了GDAL库中的GDALDestroyDriverManager函数,该函数用于在main函数退出前销毁GDALDriverManager singleton对象。文章指出在其他线程仍使用GDAL对象时不应调用此函数,并对是否应由driver的析构函数负责清理工作提出了疑问。作者通过查看源代码来理解GDAL内部的工作原理,特别提到了GeoTiff驱动的析构过程,对于C函数指针代替虚函数的设计提出了一定的质疑。
597

被折叠的 条评论
为什么被折叠?



