[Insight-developers] Roll back MetaDataObject and Dicitonary changes
Hans J. Johnson
hans-johnson@uiowa.edu
20 Mar 2003 12:06:41 -0600
Bill,
I have been spent most of this morning reviewing the changes you made
the itkMetaDataDictionary, and itkAnalyzeImageIO, and I would really
like to roll as many of those changes back as possible.
Will you please tell me why you feel these changes are necessary? I do
not have access to the borland compilers, (or VC7 today).
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1)^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#if (defined(__sgi) && !defined(__GNUC__))
outval =
reinterpret_cast<MetaDataObject <T>
*>(Dictionary[key].GetPointer())->GetMetaData
ObjectValue();
#else
outval =
dynamic_cast<MetaDataObject <T>
*>(Dictionary[key].GetPointer())->GetMetaDataObje
ctValue();
#endif
from page 10.4.11 pg 256 of the Stroustrup book:
========================================================================
The reinterpret_cast is the crudest and potentially nastiest of the type
conversion operators. In most caes, it simply yeilds a value with the
same bit pattern as it's argument wit the type required . Thus, it can
be used for the inherently implementation-depend, dangerous, and
occasionally absolutely necessary activity of converting interger values
to pointers, and vice versa.
========================================================================
I strongly believe that this needs to be a dynamic_cast down the
inheritance structure.
I have rolled this back in my experimental builds, and it compiles and
the MetaDataDictionary tests pass with the SGI compilers MIPSPro
compilers.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2)^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
a)==============================================================
template <class T>
inline bool ExposeMetaData
(
MetaDataDictionary &Dictionary,
const char *key,
T &outval
)
{
return ExposeMetaData(Dictionary, std::string(key), outval);
}
} // end namespace itk
b)==============================================================
template <class T>
inline bool ExposeMetaData
(
MetaDataDictionary &Dictionary,
const std::string key,
T &outval
)
{
//blah the real work
}
==================================================================
How does (a) differ functionally from (b) when the key argument is send
in as a const char *?
In both cases a std::string is instantiated and inintialized with that
const char * variable.
If feel that the (a) method is not needed. I have rolled this back in
my experimental builds, and it compiles and the MetaDataDictionary test
pass with the SGI and GCC 2.96, GCC 3.2 and icc, compilers.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3)^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The (b) option
a)==============================================================
{
char temp[2048];
strncpy(temp,"FirstValue",10);//Note this is necessary because the
array is not necessarily null terminated.
temp[10]='\0';
itk::EncapsulateMetaData<char *>(thisDic,"ITK_FileOriginator",temp);
strncpy(temp,"SecondValue",18);//Note this is necessary because the
array is not necessarily null terminated.
temp[18]='\0';
itk::EncapsulateMetaData<char *>(thisDic,"ITK_ImageFileBaseName",temp);
}//End of scope
b)==============================================================
{
char temp[2048];
strncpy(temp,"FirstValue",10);//Note this is necessary because the
array is not necessarily null terminated.
temp[10]='\0';
itk::EncapsulateMetaData<std::string>(thisDic,"ITK_FileOriginator",temp);
strncpy(temp,"SecondValue",18);//Note this is necessary because the
array is not necessarily null terminated.
temp[18]='\0';
itk::EncapsulateMetaData<std::string>(thisDic,"ITK_ImageFileBaseName",temp);
}//End of scope
=========================================================================
Assume the char pointer temp is at memory location 0x1234
The (a) method will result in a meta data dictionary will be two entries
<std::string="ITK_FileOriginator",SmartPoiner<MetaDataObjectBase>->GetMetaDataValue()=char *=0x1234>
<std::string="ITK_ImageFileBaseName",SmartPoiner<MetaDataObjectBase>->GetMetaDataValue()=char *=0x1234>
Also note that the temp memory is not valid outside of this small scope.
The (b) method will result in a meta data dictionary will be two entries
<std::string="ITK_FileOriginator",SmartPoiner<MetaDataObjectBase>->GetMetaDataValue()=std::string("FirstValue")>
<std::string="ITK_ImageFileBaseName",SmartPoiner<MetaDataObjectBase>->GetMetaDataValue()=std::string("SecondValue")>
I have tested this under the SGI compilers, and the gcc 2.96 and gcc
3.2, icc, compilers.
Thanks for looking into this.
Thanks,
Hans
PS: More info.
Valgrind Memory checker:
gcc 2.96 compilers:
-------------------------------------------------------------------------------------
valgrind --leak-check=yes -v
/IPLlinux/robin+home/scratch/hjohnson/src/buildhome/athlon/DEBUG/bin/itkCommonTests itkMetaDataDictionaryTest
...
==18107== LEAK SUMMARY:
==18107== definitely lost: 0 bytes in 0 blocks.
==18107== possibly lost: 0 bytes in 0 blocks.
...
-------------------------------------------------------------------------------------
valgrind --leak-check=yes -v
/IPLlinux/robin+home/scratch/hjohnson/src/buildhome/athlon/DEBUG/bin/itkIOTests itkAnalyzeImageIOTest
...
==18132== LEAK SUMMARY:
==18132== definitely lost: 0 bytes in 0 blocks.
==18132== possibly lost: 0 bytes in 0 blocks.
...