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