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