Here comes the output of the test showing the problem.
You can see that the destructors are called in opposite order to the
destructors.
Also the output should show "test5test" -- but it shows garbage
because no constructor was called for this memory location.
The destructor attempts to call delete[] one some uninitialized
pointer.
CString::CString(): this==0x7fbfff8d30
CString::CString(): this==0x7fbfff8c80
CString::CString(): this==0x7fbfff8dc0
CString::CString(): this==0x7fbfff8d60
CString::CString(): this==0x7fbfff8d00
testÉtest
CString::~CString(): this==0x7fbfff8d00
CString::~CString(): this==0x7fbfff8d60
CString::~CString(): this==0x7fbfff8dc0
CString::~CString(): this==0x7fbfff8d90
free(): invalid pointer 0x7fbfff8c88!
CString::~CString(): this==0x7fbfff8d30
If you dig deep into this code you will find that one object is of a
type derived from CString.
This is where the compiler calculates the wrong address.
Peter
#ifndef CString_h_included
#define CString_h_included
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4018 4146)
#endif
#include <string.h>
#include <iostream>
#include <stdarg.h>
#include <memory>
#ifdef __GNUC__
#include <stdio.h>
#include <ctype.h>
#include <locale.h>
#else
#include <locale>
#endif
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#ifndef classlib_export_h_included
#define classlib_export_h_included
#ifdef _MSC_VER
#if (_MSC_VER <= 1200)
#ifndef for
#define for if(0); else for
#endif
#endif
#ifdef __CLASSLIB_EXPORT__
#undef __CLASSLIB_EXPORT__
#define __CLASSLIB_EXPORT__
#endif
#ifdef GG_GLOBAL_LIB_EXPORTS
#ifndef __CLASSLIB_EXPORT__
#define __CLASSLIB_EXPORT__ __declspec(dllexport)
#endif
#else
#if (_MSC_VER <= 1200)
#ifndef __CLASSLIB_EXPORT__
#define __CLASSLIB_EXPORT__ __declspec(dllimport)
#endif
#endif
#endif
#else
#define __CLASSLIB_EXPORT__
#endif
#endif // !classlib_export_h_included
// A auto_ptr for arrays -- since delete[] must be used std::auto_ptr
cannot be used
// for pointers to arrays of non-trivial objects.
#ifndef CArrayAutoPtr_h_included
#define CArrayAutoPtr_h_included
#ifndef __INSIDE_VA2GG__
#endif
namespace xpedion
{
template<class T>
class CArrayAutoPtr
{ private:
mutable T *m_pa;
public:
inline CArrayAutoPtr(T *_p = 0)
:m_pa(_p)
{
}
inline CArrayAutoPtr(const CArrayAutoPtr<T> &_r)
:m_pa(_r.m_pa)
{ _r.m_pa = 0;
}
inline ~CArrayAutoPtr(void)
{ delete[] m_pa;
}
inline CArrayAutoPtr<T> &operator=(const CArrayAutoPtr<T> &_r)
{ delete[] m_pa;
m_pa = _r.m_pa;
_r.m_pa = 0;
return *this;
}
inline operator T *(void) const
{ return m_pa;
}
inline T *get(void) const
{ return m_pa;
}
inline T *getPtr(void) const
{ return m_pa;
}
inline bool isOwner(void) const
{ return m_pa != 0;
}
inline T *release(void)
{ T *tmp = m_pa;
m_pa = 0;
return tmp;
}
inline T *detach(void)
{ return release();
}
inline void reset(T *_p = 0)
{ if (m_pa != _p)
{ delete [] m_pa;
m_pa = _p;
}
}
};
}
#endif // !CArrayAutoPtr_h_included
/*
$Header: /cvsroot/classlib/CArrayAutoPtr.h,v 1.9 2007/04/19 20:30:15
pfoelsch Exp $
*/
//#include <varargs.h>
//#ifndef _MSC_VER
//#define _vsnprintf vsnprintf
//#endif
namespace xpedion
{
template<class __C__=char, const unsigned int __SIZE__=32>
class CString
{ private:
__C__ *m_p;
__C__ m_ac[__SIZE__];
unsigned int m_iNumberOfChars;
// not used -- immutable
inline CString<__C__, __SIZE__> &operator=(const CString<__C__,
__SIZE__> &_r)
{ return *this;
}
public:
typedef enum
{ eToLower,
eToUpper
} eOp;
inline CString(eOp _e, const CString<__C__, __SIZE__> &_r)
{ m_iNumberOfChars = _r.m_iNumberOfChars;
printf("CString::CString(): this==0x%lx\n", this);
if (m_iNumberOfChars > sizeof m_ac/sizeof m_ac[0])
m_p = new __C__[m_iNumberOfChars];
else
m_p = m_ac;
switch (_e)
{ default:
::memcpy(m_p, _r.m_p, m_iNumberOfChars*sizeof*m_p);
break;
case eToLower:
for (unsigned int i = 0; i < m_iNumberOfChars; i++)
#ifdef __GNUC__
m_p[i] = ::tolower(_r.m_p[i]);
#else
m_p[i] = std::tolower(_r.m_p[i], std::locale::classic());
#endif
break;
case eToUpper:
for (unsigned int i = 0; i < m_iNumberOfChars; i++)
#ifdef __GNUC__
m_p[i] = ::toupper(_r.m_p[i]);
#else
m_p[i] = std::toupper(_r.m_p[i], std::locale::classic());
#endif
break;
}
}
inline CString(void)
{ m_p = m_ac;
printf("CString::CString(): this==0x%lx\n", this);
m_ac[0] = 0;
m_iNumberOfChars = 1;
}
inline CString(const __C__ _c)
{ m_p = m_ac;
printf("CString::CString(): this==0x%lx\n", this);
m_ac[0] = _c;
m_ac[1] = 0;
m_iNumberOfChars = 2;
}
inline CString(const CString<__C__, __SIZE__> &_r1, const
CString<__C__, __SIZE__> &_r2)
{ m_iNumberOfChars = _r1.m_iNumberOfChars + _r2.m_iNumberOfChars - 1;
printf("CString::CString(): this==0x%lx\n", this);
if (m_iNumberOfChars > sizeof m_ac/sizeof m_ac[0])
m_p = new __C__[m_iNumberOfChars];
else
m_p = m_ac;
::memcpy(m_p, _r1.m_p, _r1.m_iNumberOfChars*sizeof*m_p);
::memcpy(m_p + _r1.m_iNumberOfChars - 1, _r2.m_p,
_r2.m_iNumberOfChars*sizeof*m_p);
}
inline CString(const __C__ *_p1, const __C__ *_p2)
{
printf("CString::CString(): this==0x%lx\n", this);
if (!_p1)
{ static const __C__ c = 0;
_p1 = &c;
}
if (!_p2)
{ static const __C__ c = 0;
_p2 = &c;
}
const unsigned int i1 = strlen(_p1) + 1;
const unsigned int i2 = strlen(_p2) + 1;
m_iNumberOfChars = i1 + i2 - 1;
if (m_iNumberOfChars > sizeof m_ac/sizeof m_ac[0])
m_p = new __C__[m_iNumberOfChars];
else
m_p = m_ac;
::memcpy(m_p, _p1, i1*sizeof*m_p);
::memcpy(m_p + i1 - 1, _p2, i2*sizeof*m_p);
}
inline CString(const __C__ *_p, unsigned int _iLen)
{
printf("CString::CString(): this==0x%lx\n", this);
if (!_p)
{ static const __C__ c = 0;
_p = &c;
}
m_iNumberOfChars = _iLen + 1;
if (m_iNumberOfChars > sizeof m_ac/sizeof m_ac[0])
m_p = new __C__[m_iNumberOfChars];
else
m_p = m_ac;
::memcpy(m_p, _p, (m_iNumberOfChars - 1)*sizeof*_p);
m_p[m_iNumberOfChars - 1] = 0;
}
inline CString(const __C__ *_p)
{
printf("CString::CString(): this==0x%lx\n", this);
if (!_p)
{ static const __C__ c = 0;
_p = &c;
}
m_iNumberOfChars = strlen(_p) + 1;
if (m_iNumberOfChars > sizeof m_ac/sizeof m_ac[0])
m_p = new __C__[m_iNumberOfChars];
else
m_p = m_ac;
::memcpy(m_p, _p, m_iNumberOfChars*sizeof*_p);
}
inline CString(const CString<__C__, __SIZE__> &_r)
{
printf("CString::CString(): this==0x%lx\n", this);
m_iNumberOfChars = _r.m_iNumberOfChars;
if (m_iNumberOfChars > sizeof m_ac/sizeof m_ac[0])
m_p = new __C__[m_iNumberOfChars];
else
m_p = m_ac;
::memcpy(m_p, _r.m_p, m_iNumberOfChars*sizeof*m_p);
}
inline unsigned int getNumberOfChars(void) const
{ return m_iNumberOfChars;
}
inline CString<__C__, __SIZE__> operator+(const CString<__C__,
__SIZE__> &_r) const
{ return CString<__C__, __SIZE__>(*this, _r);
}
inline const __C__ *getString(void) const
{ return m_p;
}
inline operator const __C__ *(void) const
{ return m_p;
}
inline ~CString(void)
{
printf("CString::~CString(): this==0x%lx\n", this);
if (m_p != m_ac)
delete[] m_p;
}
inline bool operator==(const __C__ *_p) const
{ return _p ? (strcmp(m_p, _p) == 0) : false;
}
inline bool operator<(const __C__ *_p) const
{ return _p ? (strcmp(m_p, _p) < 0) : false;
}
inline bool operator>(const __C__ *_p) const
{ return _p ? (strcmp(m_p, _p) > 0) : false;
}
inline CString<__C__, __SIZE__> tolower(void) const
{ return CString<__C__, __SIZE__>(eToLower, *this);
}
inline CString<__C__, __SIZE__> toupper(void) const
{ return CString<__C__, __SIZE__>(eToUpper, *this);
}
inline static int strcmp(const __C__ *_p1, const __C__ *_p2)
{ for (; *_p1 && *_p2; _p1++, _p2++)
if (*_p1 == *_p2)
continue;
else
if (*_p1 < *_p2)
return -1;
else
return 1;
if (*_p1 == *_p2)
return 0;
else
if (*_p1 < *_p2)
return -1;
else
return 1;
}
static inline unsigned int strlen(const __C__ * const _p)
{ unsigned int i;
for (i = 0; _p[i]; i++)
;
return i;
}
static inline const __C__ *strchr(const __C__ * const _p, const __C__
_c)
{ for (unsigned int i = 0; _p[i]; i++)
if (_p[i] == _c)
return _p + i;
return 0;
}
static inline const __C__ *strrchr(const __C__ * const _p, const
__C__ _c)
{ for (unsigned int i = strlen(_p) - 1; i; i--)
if (_p[i] == _c)
return _p + i;
if (_p[0] == _c)
return _p;
else
return 0;
}
static CString<__C__, __SIZE__> sprintf(const __C__ *_pFormat, ...)
{
::va_list args;
__C__ ac[__SIZE__];
__C__ *p = ac;
unsigned int iSize = sizeof ac/sizeof ac[0];
xpedion::CArrayAutoPtr<__C__> s;
#ifdef _MSC_VER
while (1)
{
//p[iSize - 1] = 0;
va_start(args, _pFormat);
if (::_vsnprintf(p, iSize, _pFormat, args) < 0)
{ va_end(args);
iSize += __SIZE__;
s = xpedion::CArrayAutoPtr<__C__>(p = new __C__[iSize]);
}
else
{ va_end(args);
break;
}
}
#else
#if (defined __SUNPRO_CC || defined __GNUC__)
unsigned int iSizeNeeded;
while (1)
{ va_start(args, _pFormat);
iSizeNeeded = ::vsnprintf(p, iSize, _pFormat, args) + 1;
va_end(args);
if (iSizeNeeded > iSize)
{ iSize = iSizeNeeded;
xpedion::CArrayAutoPtr<__C__> tmp(p = new __C__[iSize]);
s = tmp;
}
else
break;
}
#else
#error please check vsnprintf implementation
#endif
#endif
return p;
}
};
#if (defined(_MSC_VER) && (_MSC_VER < 1400))
template class __CLASSLIB_EXPORT__ CString<char>;
#endif
typedef CString<char> CCharString;
}
#endif // !CString_h_included
/*
$Header: /cvsroot/classlib/CString.h,v 1.24 2007/06/22 19:57:24
cshyamsu Exp $
*/
#if 0
using namespace xpedion;
int main(int argc, char **argv)
{
CString<char, 27> s(CString<char, 27>::sprintf("%e - %e", 3.1415926,
383.1415926));
return 0;
}
#endif
#ifndef CSprintf_h_included
#define CSprintf_h_included
#pragma warning(push)
#pragma warning(disable: 4127)
#include <stdio.h>
#pragma warning(pop)
#ifndef NO_NAMESPACE
namespace xpedion
{
#endif
template<class __TYPE__, const char *__FORMAT__, unsigned int
__SIZE__>
class CSprintf:public CString<char, __SIZE__>
{ public:
inline static CString<char, __SIZE__> format(__TYPE__ _d)
{ char ac[__SIZE__];
static const char * const p = __FORMAT__;
//printf("%s\n", p);
#ifdef _MSC_VER
_snprintf(ac, sizeof ac/sizeof ac[0], __FORMAT__, _d);
#else
snprintf(
ac,
sizeof ac/sizeof ac[0],
#if 0
__FORMAT__,
#else
p,
#endif
_d);
#endif
return CString<char, __SIZE__>(ac);
}
inline CSprintf(__TYPE__ _d)
:CString<char, __SIZE__>(format(_d))
{
}
};
extern const char g_acSprintfDoubleFormat[];
extern const char g_acSprintfUnsignedIntFormat[];
extern const char g_acSprintfIntFormat[];
typedef CSprintf<double, g_acSprintfDoubleFormat, 32> CSprintfDouble;
typedef CSprintf<unsigned int, g_acSprintfUnsignedIntFormat, 32>
CSprintfUnsignedInt;
typedef CSprintf<int, g_acSprintfIntFormat, 32> CSprintfInt;
template class __CLASSLIB_EXPORT__ CSprintf<double,
g_acSprintfDoubleFormat, 32>;
template class __CLASSLIB_EXPORT__ CSprintf<unsigned int,
g_acSprintfUnsignedIntFormat, 32>;
template class __CLASSLIB_EXPORT__ CSprintf<int, g_acSprintfIntFormat,
32>;
const char g_acSprintfDoubleFormat[] = "%.16e";
const char g_acSprintfUnsignedIntFormat[] = "%u";
const char g_acSprintfIntFormat[] = "%d";
#ifndef NO_NAMESPACE
}
#endif
#endif // !CSprintf_h_included
/*
$Header: /cvsroot/classlib/CSprintf.h,v 1.10 2005/05/12 06:51:09
daniela Exp $
*/
int main(int argc, char **argv)
{
printf("%s\n", (xpedion::CString<char>("test") +
xpedion::CSprintfUnsignedInt(5) + "test").getString());
return 0;
}