>
> > 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.


What I mean is the following:
PdfArray() is constructed, automatically PdfObject is constructed by the
compiler.
BUT PdfArray() and PdfObject are also destroyed automatically when the
function terminates. This is because PdfArray() is constructed on the stack
and not on the heap.


>
> 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.


Correct, temporary array.


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



Correct, but rObject is still the temporary array.


>
> 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?


Well it seems logical and should work if everything is deep copy
constructed. The problem I saw was that the stored array pointer was
invalid. The stored array pointed to the temporary PdfArray. Maybe it has to
do with the STL not properly making a deep copy.



>
> >
> > 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.


Ok, this probably explains why I got error 2. But I'm not sure. If this
constructor was actually called, the "NOT AN ARRAY" should have been thrown
much earlier.

 I had many troubles in the past with constructors taking a single argument
and automatic type conversions. I prefix all constructors with the
"explicit" keyword to prevent this kind of type casting.

Regards,
MIrco
------------------------------------------------------------------------------
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
[email protected]
https://lists.sourceforge.net/lists/listinfo/podofo-users

Reply via email to