bug-gplusplus
[Top][All Lists]
Advanced

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

pointer corruption bug w/ template classes


From: Ian Williams
Subject: pointer corruption bug w/ template classes
Date: Wed, 16 May 2001 19:59:29 -0700

Hi,

There appears to be a bug with the g++ compiler when using template classes
and the attached program shows the issue.

The version of the g++ compiler used is egcs-c++-1.1.2-30 (from RedHat 6.2)
and the hardware was an SGI 230 system w/ Pentium III 733 MHz with Via
Apollo Pro chip set and PC133 SDRAM.

The template class is used to define a buffer and a further subClass deals
with a buffer of arrays (such as points). It seems that when an array class
is instantiated and an element is added (via the BufferV:add method) the
address of the array address gets corrupted through the call. To show this
the program prints out the data before, during and after the BufferV:add
call and the results after entering BufferV:add yield garbage.

As documented in the program, the weird thing is that for the cases where
BufferV is instantiated with F=int[3] or F=float[3], adding 3 to the array
index in BufferV:add delivers the correct elements. I couldn't find any
similar thing when BufferV is intantiated with F=double[3] though.

Thanks in advance for any information/suggestions.

Ian M. Williams.



----------------------------------------------------------------------------
-----------------------------------

/*      Compile:        g++ -o test test.c++    */

#include <string.h>
#include <iostream.h>
#include <fstream.h>
#include <stdlib.h>

#ifndef TRUE
#define TRUE    1
#endif

#ifndef FALSE
#define FALSE   0
#endif

template <class T, class F> // T="To" the storage format for the buffer
                                // F="From", the storage format from which
the
                                //           data comes


class Buffer
{
public:

        Buffer(int length=100, char* label=NULL);
        virtual ~Buffer();

        virtual bool    add(F item) = 0;
        T*                      buf() const;
        int                     bufLength() const;
        bool                    canAddTo();
        void                    reset();

protected:

        T*              mBuffer;
        int             mInBuffer;

private:

        Buffer(const Buffer<T,F>& b);

        int     mBufferLength;
        bool    mOverflowReported;
        char*   mBufferName;
};

template <class T, class F>
Buffer<T,F>::Buffer(int length, char* label) :
                mBufferLength(length), mOverflowReported(FALSE),
                mBuffer(NULL), mInBuffer(0), mBufferName(NULL)
{
        mBuffer = new T[length];
        if (label != NULL)
        {
                mBufferName = new char[strlen(label)+1];
                strcpy(mBufferName,label);
        }
}

template <class T, class F>
Buffer<T,F>::Buffer(const Buffer<T,F>& b) :
                mBufferLength(0), mOverflowReported(FALSE),
                mBuffer(NULL), mInBuffer(0), mBufferName(NULL)
{
}

template <class T, class F>
Buffer<T,F>::~Buffer()
{
        if (mBuffer != NULL)
        {
                delete [] mBuffer;
                mBuffer = NULL;
                mBufferLength = 0;
                reset();
        }
        if (mBufferName != NULL)
        {
                delete [] mBufferName;
                mBufferName = NULL;
        }
}

template <class T, class F>
T*
Buffer<T,F>::buf() const
{
        return mBuffer;
}

template <class T, class F>
int
Buffer<T,F>::bufLength() const
{
        return mInBuffer;
}

template <class T, class F>
bool
Buffer<T,F>::canAddTo()
{
        if ( mInBuffer == mBufferLength )
        {
                if (!mOverflowReported)
                {
                        mOverflowReported = TRUE;
                        if (mBufferName != NULL)
                                cerr << mBufferName << ": ";
                        cerr << "Buffer overflow\n";
                }
                return FALSE;
        }
        return TRUE;
}

template <class T, class F>
void
Buffer<T,F>:: reset()
{
        mOverflowReported = FALSE;
        mInBuffer = 0;
}

//////////////// Subclass for buffering arrays /////////////////////////////

template <class T, class F>
class BufferV : public Buffer<T,F>
{
public:
        BufferV(int length=100, char* label=NULL);
        virtual ~BufferV();

        virtual bool    add(F item);

private:
        BufferV(const BufferV<T,F>& b);
};

template <class T, class F>
BufferV<T,F>::BufferV(int length, char* label) : Buffer<T,F>(length,label)
{
}

template <class T, class F>
BufferV<T,F>::BufferV(const BufferV<T,F>& b) : Buffer<T,F>(b)
{
}

template <class T, class F>
BufferV<T,F>::~BufferV()
{
}

template <class T, class F>
bool
BufferV<T,F>::add(F item)
{

        cout    << "item = " << item[0] << ", " 
                << item[1] << ", " << item[2] <<  endl;
/*
        For some reason the following line yields the correct output
        when instantiated with F = int[3] or F = float[3]               
        cout    << "item = " << item[0+3] << ", " 
                << item[1+3] << ", " << item[2+3] <<  endl;
*/

        if (Buffer<T,F>::canAddTo())
        {
                cout << "mBuffer[" << mInBuffer << "] = ";
                for (int i=0 ; i<3 ; i++) {
/* 
        See above when instanciated with F = int[3] and float[3]        
                        mBuffer[mInBuffer][i] = item[i+3];
*/
                        mBuffer[mInBuffer][i] = item[i];
                        cout << mBuffer[mInBuffer][i] << ", ";
                }
                cout << endl;
                mInBuffer++;
                return TRUE;
        }
        return FALSE;
}



//typedef int  Dxyz[3],  *DxyzP;
//typedef float  Dxyz[3],  *DxyzP;
typedef double  Dxyz[3],  *DxyzP;

static BufferV<Dxyz,Dxyz>       faceVertexBuf(10,"faceVertexBuf");

Dxyz    input_points[4]={       {1.0, -1.0, 1.0},{1.0, 1.0, -1.0},
                                {1.0, 1.0, 1.0},{1.0, -1.0, 1.0} };

int main (int argc, char* argv[])
{
        int i = 0, index;
        faceVertexBuf.reset();

        for (i=0;i<4; i++) {

                index = faceVertexBuf.bufLength();
                Dxyz    temp = {input_points[i][0], 
                                input_points[i][1], 
                                input_points[i][2]};

                cout << "Input = " << temp[0] << ", " 
                     << temp[1] << ", " <<  temp[2] << endl; ;

                faceVertexBuf.add(temp);
                DxyzP tempP = faceVertexBuf.buf()[index];

                cout << "Output = " << tempP[0] << ", " 
                     << tempP[1] << ", " <<  tempP[2] << endl; ;

        }

        return 0;
}




reply via email to

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