On Mon, 2009-07-27 at 13:25 +0200, Mirco Babin wrote:

> The PdfPainter is not the problem, but the CreatePage() is.
>  
> 1)  
> void PdfPagesTree::InsertPage( int nAfterPageNumber, PdfObject*
> pPage )
> PdfObject* pPageBefore = this->GetPageNode( nAfterPageNumber,
> this->GetRoot(), lstParents ); //MEMORY EXCEPTION
> 
> I have traced it down into PdfPagesTree. 
> The constructor reads:
> PdfPagesTree::PdfPagesTree( PdfVecObjects* pParent )
>     : PdfElement( "Pages", pParent ),
>       m_cache( 0 )
> {
>     GetObject()->GetDictionary().AddKey( "Kids", PdfArray() ); //
> kids->Reference() 
>     GetObject()->GetDictionary().AddKey( "Count",
> PdfObject( static_cast<pdf_int64>(0LL) ) );
> }
>  
> The problem resides in the PdfArray(). This does construct an empty
> array, but at the function end, this array is also automatically
> destroyed. But the pointer to the destroyed array is stored in the
> Dictionary.

I'm having trouble understanding your explanation. It does not appear to
match the behaviour of the code above.

This:

     GetObject()->GetDictionary().AddKey( "Kids", PdfArray() ); //
kids->Reference()

obtains a reference to a PdfDictionary& and calls AddKey(const PdfName&,
const PdfObject&) on it.

The first argument is a `const char*', so the compiler creates a
temporary PdfName by calling `PdfName::PdfName(const char*)' with it. A
const reference to this temporary is then passed to AddKey.

The second argument is a temporary PdfArray instance. As GetKey expects
a PdfObject the compiler creates a new PdfObject temporary with the
PdfObject::PdfObject(const PdfArray&) constructor, and passes a const
reference to that temporary to AddKey.

Now, in:

       void PdfDictionary::AddKey( const PdfName & identifier, const
PdfObject & rObject )

the passed PdfObject is explicitly copy-constructed into the internal
key map:

        m_mapKeys[identifier] = new PdfObject( rObject );

operator new() calls PdfObject::PdfObject(const PdfObject&) to
copy-construct the PdfObject. That copy-constructs the PdfVariant parent
type first, which in turn explicitly copies the PdfArray it's storing a
pointer to in its UVariant as a PdfDataType* pData, as you can see here:

PdfVariant::PdfVariant( const PdfVariant & rhs )
{
    Init();
    this->operator=(rhs);
    SetDirty( false );
}

const PdfVariant & PdfVariant::operator=( const PdfVariant & rhs )
{
    Clear();
    rhs.DelayedLoad();
    m_eDataType      = rhs.m_eDataType;
    switch( m_eDataType )
    {
        case ePdfDataType_Array:
        {
            if( rhs.m_Data.pData )
                m_Data.pData = new
PdfArray( *(static_cast<PdfArray*>(rhs.m_Data.pData)) );
            break;
        }
        // blah blah blah
    }
    SetDirty( true );
    return (*this);
}


I don't see how that matches what you've described. Have I missed
something obvious? If not, can you provide a more detailed explanation
going through the flow of execution to show where exactly the problem
arises?

>  
> I adjusted this to:
> PdfPagesTree::PdfPagesTree( PdfVecObjects* pParent )
>     : PdfElement( "Pages", pParent ),
>       m_cache( 0 )
> {
>     PdfArray* kids_array = new PdfArray();
>     PdfObject* kids_object = new PdfObject(kids_array);
>     PdfObject* count_object = new
> PdfObject( static_cast<pdf_int64>(0LL) );
>     GetObject()->GetDictionary().AddKey( "Kids", kids_object ); //
> kids->Reference()
>     GetObject()->GetDictionary().AddKey( "Count", count_object );
> }
> 
Er, that's wrong. You're leaking memory all over the place, or you would
be if the code worked at all. Once you resolve the overloads what that
code actually does is construct a new heap-based PdfArray, then call:

PdfObject::PdfObject(pdf_uint64)

with it! Or, at least, it should if your compiler implements C++
properly.


I've committed a change to PdfObject.h to svn that'll help compilers
catch this and report it as an error. Something like:

error: ‘PoDoFo::PdfObject::PdfObject(T*) [with T = PoDoFo::PdfArray]’ is
private



> 2)
> void PdfPagesTree::InsertPage( int nAfterPageNumber, PdfObject*
> pPage )
> InsertPageIntoNode( m_pObject, lstPagesTree, -1, pPage ); //EXCEPTION
>  
> calls:
> void PdfPagesTree::InsertPageIntoNode( PdfObject* pParent, const
> PdfObjectList & rlstParents, 
>                                        int nIndex, PdfObject* pPage )
>     const PdfArray oldKids =
> pParent->GetDictionary().GetKey( PdfName("Kids") )->GetArray(); //throws Not 
> an array

Let me come back to that one once we've tracked down the other problems.

--
Craig Ringer



------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day 
trial. Simplify your report design, integration and deployment - and focus on 
what you do best, core application coding. Discover what's new with 
Crystal Reports now.  http://p.sf.net/sfu/bobj-july
_______________________________________________
Podofo-users mailing list
Podofo-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/podofo-users

Reply via email to