[Gdal-dev] GDAL CPLError and C++ Exceptions

Ray Gardener rayg at daylongraphics.com
Wed Nov 29 17:24:34 EST 2006


Yes, you're absolutely right; my bad, sorry about that. That's what I 
get for hastily coding examples after midnight. :)  The ownership policy 
on original objects needs to be defined better.

Ray


Mateusz Loskot wrote:
> Ray Gardener wrote:
>> fwiw, for those preferring exception-based error reporting all around:
>>
>> Since GDAL implements return code based error reporting, if you don't
>> mind wrapping the GDAL APIs, you can create an exceptions-based
>> interface, e.g. if using the GDAL C++ API:
>>
>> class GDALDataset_plus
>> {
>>   public:
>>     // After normally instancing a dataset, instance a myDataset
>>     // and assign the original dataset to this member var
>>     // (or if instancing locally, use the second ctor).
>>     GDALDataset* m_pDataset;
>>
>>     GDALDataset_plus() : m_pDataset(NULL) {}
>>     GDALDataset_plus(GDALDataset* p) : m_pDataset(p) {}
>>     virtual ~GDALDataset_plus() { if(m_pDataset) delete m_pDataset; }
>>
>>     void AddBand(type, options)
>>     {
>>         assert_ptr(m_pDataset);
>>         if(CE_None != m_pDataset->AddBand(type, options))
>>            throw gdal_exception();
>>     }
>>
>>     // ... wrappers around remaining GDALDataset methods
>> };
>>
>> // ... GDALxxx_plus class versions of remaining GDAL classes
>>
>>
>> And then you can do stuff like:
>>
>>   GDALDataset dataset_org;
>>   GDALDataset_plus dataset(&dataset_org);
> 
> Ray,
> 
> This code of usage is ill-formed.
> dataset_org is an object with automatic storage duration.
> Now, pointer to dataset_org is passed to constructor of
> GDALDataset_plus, with implicit *ownership transfer*.
> So, it results in m_pDataset pointing to automatic object.
> 
> Next, 1) destructor of GDALDataset_plus calls delete on pointer to
> automatic object (dataset_org),
> 2) dataset_org will be destroyed automatically on the scope exit (EOF
> object lifetime).
> 
> You must not call delete on automatic storage duration objects.
> 
>>   try
>>   {
>>      dataset.AddBand(type, options);
>>      // other stuff, with no checking of return codes
>>      // since the _plus classes return 'void'
>>   }
>>   catch(gdal_exception& e) { msg("GDAL exception occurred"); }
>>   catch(...) { msg("Unknown error"); }
> 
> OK, but the GDALDataset is allocated dynamically and returned by pointer
> from GDAL and it needs to be closed and destroyed explicitly by the wrapper.
> In the example above, 'dataset' of type of GDALDataset is presented
> as local object what's very rare or even impossible situation when using
> GDAL.
> 
>> The wrappers also enable other niceties, like avoiding having to include
>> error variables as arguments (if you always prefer such cases to just
>> throw an exception instead), and having the return type of a function
>> always be non-error-related. e.g.,
>>   int foo(void) instead of errcode foo(int* p)
> 
> It's also possible to use smart pointers like shared_ptr with custom
> deleter, as a simple wrapper:
> 
> boost::shared_ptr<OGRFeature> feature(layer->GetFeature(0),
>                                       OGRFeature::DestroyFeature);
> 
> Feature object returned by GetFeature will be destroyed properly
> by DestroyFeature call.
> 
> Cheers




More information about the Gdal-dev mailing list