0

I have a weird problem in C++:

My program crashes when I want to new a uint8_t* in an initializer list of my PixelIterator class.

Here is the call stack:

#0 00000000 0x0040b030 in __cxa_throw() (??:??)
#1 00000000 0x004047e1 in operator new() (??:??)
#2 004018B5 PixelIterator(this=0x28fe2c, _oth=0x5d5154, iOffset=300, iPitch=300, iBpp=2 '\002') (C:\Users\David\Desktop\SDL++\SDLPP_Sprite.cpp:34)
#3 0041E0CC SDL::Sprite::At(this=0x5d1548, iX=150, iY=0) (C:/Users/David/Desktop/SDL++/SDLPP_Sprite.hpp:89)
#4 0041E5B0 MyApp::OnInit(this=0x5d1520, iArgc=1, ppcArgv=0x5d1498) (C:\Users\David\Desktop\SDL++\main.cpp:37)
#5 00402641 SDL::Application::Run(this=0x5d1520, pScreen=0x5d4df0, iArgc=1, ppcArgv=0x5d1498) (C:\Users\David\Desktop\SDL++\SDLPP_Application.cpp:24)
#6 004020A3 main(iArgc=1, ppcArgv=0x5d1498) (C:\Users\David\Desktop\SDL++\main.cpp:103)

First of all, the PixelIterator class inherits from BaseIterator:

template< typename T >
class BaseIterator
{
public:
    typedef T ValueType;

    BaseIterator( void )
        :   ptr( NULL )
    {}

    BaseIterator( const BaseIterator< T >& _oth )
        :   ptr( _oth.ptr )
    {}

    BaseIterator( T * p )
        :   ptr( p )
    {}

    T& operator*( void )
    {
        assert( ptr != NULL );
        return *ptr;
    }

    T* operator->( void )
    {
        assert( ptr != NULL );
        return ptr;
    }

    bool operator==( const BaseIterator< T >& _oth )
    {
        return ptr == _oth.ptr;
    }

    bool operator!=( const BaseIterator< T >& _oth )
    {
        return ptr != _oth.ptr;
    }

    bool operator<( const BaseIterator< T >& _oth )
    {
        return ptr < _oth.ptr;
    }

    bool operator<=( const BaseIterator< T >& _oth )
    {
        return ptr <= _oth.ptr;
    }

    bool operator>( const BaseIterator< T >& _oth )
    {
        return ptr > _oth.ptr;
    }

    bool operator>=( const BaseIterator< T >& _oth )
    {
        return ptr >= _oth.ptr;
    }

    friend ostream& operator<<( ostream& _os, const BaseIterator< T >& _this )
    {
        _os << reinterpret_cast< void* >( _this.ptr );
        return _os;
    }

protected:
    T * ptr;
};

And here is the PixelIterator class:

/**
 **  Designed to iterate through a virtual 2D array of pixels( uint8_t* )
 **/
class PixelIterator : public BaseIterator< uint8_t* >
{
public:
    PixelIterator( void );
    PixelIterator( const PixelIterator& _oth );
    PixelIterator( uint8_t ** _oth, uint32_t iOffset, uint16_t iPitch, uint8_t iBpp );
    ~PixelIterator( void );

    PixelIterator& operator=( const PixelIterator& _oth );

    PixelIterator& operator++( void ); // 1 pixel right
    PixelIterator& operator--( void ); // 1 pixel left
    PixelIterator& operator++( int unused ); // 1 pixel right
    PixelIterator& operator--( int unused ); // 1 pixel left

    PixelIterator& operator+=( uint32_t iSize ); // iSize pixel right
    PixelIterator& operator-=( uint32_t iSize ); // iSize pixel left

    PixelIterator& operator>>( uint32_t iSize ); // iSize pixel down
    PixelIterator& operator<<( uint32_t iSize ); // iSize pixel up

protected:
    uint16_t m_iPitch;
    uint8_t m_iBpp;
};

And this is the constructor, where the error happens:

Sprite::PixelIterator::PixelIterator( uint8_t ** _oth, uint32_t iOffset, uint16_t iPitch, uint8_t iBpp )
    :   BaseIterator< uint8_t* >( new uint8_t*( *_oth + iOffset ) ),
        m_iPitch( iPitch ),
        m_iBpp( iBpp )
{}

_oth is in this case a pointer to pointer to the pixel data (1D Array of void*); iOffset is the offset in the array

I am using SDL for graphics output and Code::Blocks as IDE. The size of the tested image is 150x120 pixel.

If you need more informations about code, please ask :)

EDIT:

Instantiation:

m_Img.Lock();
for( int32_t y = 0; y < m_Img.GetSurface()->h; y++ )
{
    for( SDL::Sprite::Iterator x = m_Img.At( 0, y ); x != m_Img.At( m_Img.GetSurface()->w, y ); x++ )
        *reinterpret_cast< uint16_t* >( *x ) = 0;
}
m_Img.Unlock();

SDL::Sprite::Iterator is the same as SDL::Sprite::PixelIterator (typedef). m_Img is an object of SDL::Sprite.

SDL::Sprite::At() method:

inline
Iterator At( uint32_t iX, uint32_t iY )
{
    return Iterator( reinterpret_cast< uint8_t ** >( &m_pSurface->pixels ),
                     iY * m_pSurface->pitch + iX * m_pSurface->format->BytesPerPixel,
                     m_pSurface->pitch, m_pSurface->format->BytesPerPixel );
}

m_pSurface is a pointer on a SDL_Surface

wolf633
  • 23
  • 6
  • 2
    If new crashes it could be a problem with overwritten memory in another part of the program. – dutt Jan 02 '13 at 11:26
  • 3
    If you have an issue with C++, why did you tag the question with `c`? – qrdl Jan 02 '13 at 11:26
  • You might like to show us how you instantiate `PixelIterator`. – alk Jan 02 '13 at 11:37
  • 1
    Why does `BaseIterator` hold a `uint8_t **`, and why are you `new`ing a single pointer at all, rather than holding it by value? (PS. you're also leaking that pointer AFAICS) – Useless Jan 02 '13 at 11:47
  • i updated the post. @Useless It holds a uint8_t**, because i need a pointer on uint8_t* and i need to cast this pointer( uint8_t* ) to different pointer types: uint16_t* for 16 BPP Images and uint32_t* for 32 BPP Images. And why am I leaking ? I free that memory in the destructor and before copying. – wolf633 Jan 02 '13 at 12:15
  • Your design looks flawed: you should not need to resort to pointers of pointer. The basic pixel data are of some type, say `uint8_t`, and you only need pointers to this type (you may even cast them to other pointer types, if required). – Walter Jan 02 '13 at 12:24
  • @wolf633 - so you manage the memory held in `BaseIterator` manually in the derived class? I just noticed that `BaseIterator` itself doesn't have a destructor. About casting, Walter is correct that this doesn't require pointer-to-pointer types. – Useless Jan 02 '13 at 12:34
  • @Walter -- I need to get and set the pixel when i call BaseIterator::operator*. If i am using uint8_t* only, I would get an uint8_t. So then i can not set it after casting to uint16_t ( for 16 BitsPerPixel ) or uint32_t ( for 32 BitsPerPixel ). So BaseIterator::operator* **has to** return a uint8_t*. Or is it better when i use uint8_t*& instead ? – wolf633 Jan 02 '13 at 12:49
  • @Useless -- Yes, newing/deleting only appears in PixelIterator. But do i need a destructor in BaseIterator ? If yes, does it need to be virtual ? – wolf633 Jan 02 '13 at 12:52
  • Did you examine the values of `*_oth` and `iOffset`? And what exception was thrown? was it `std::bad_alloc`? – szx Jan 02 '13 at 14:01
  • @szx -- `iOffset=300`, `*_oth` is always the first address of the pixelarray. And how do i catch an exception in an initializer list ? I do not use them often. – wolf633 Jan 02 '13 at 14:24
  • You can use a [function try-catch block](http://stackoverflow.com/q/6756931/212858), or just wrap a try-catch block around the instantiation site. – Useless Jan 02 '13 at 14:55
  • so i've written this: [link](http://pastebin.com/XZsRADKh), but nothing was thrown. – wolf633 Jan 02 '13 at 15:45
  • @wolf633 `iterator::operator*` should return a reference (`const` or not depending on the iterator type), which allows you to (1) modify the value to which the iterator refers and (2) to cast to another reference type via `reinterpret_cast(*iter)`. I repeat: if you allocate a single pointer via `new` something is terribly **wrong** with your **code**. – Walter Jan 03 '13 at 10:29
  • Big thanks Walter :). This solved my problem. But i didn't know that you can cast between reference types... – wolf633 Jan 03 '13 at 18:10

0 Answers0