bug-gplusplus
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

compiler calculates wrong address for constructor of temporary object (G


From: ExcessPhase
Subject: compiler calculates wrong address for constructor of temporary object (G++ version 4.2.2)
Date: Thu, 15 Nov 2007 13:52:58 -0800 (PST)
User-agent: G2/1.0

Below comes some example code, which shows that the compiler calls the
constructor of some temporary object with the wrong address. I deduce
this, since the addresses of constructor and destructor calls don't
line up and that there is one address in the constructor calls which
is outside of the range of the others.
When compiling using -O3 the code works fine. When compiling using -g
the bug happens.
To exhibit this I put calls to printf() into the constructor and
destructor showing the "this" pointer.
Look at the end of the code to find the main function with one call to
printf() and several temporary objects of my old string class. (Btw
I'm not using this class anymore since we have std::string.)

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;
}



reply via email to

[Prev in Thread] Current Thread [Next in Thread]