Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » VC++ / MFC » Probleme beim Serialisieren

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 <
000
12.07.2005, 15:18 Uhr
GuenniAtWork



Hi,

ich habe probleme mit dem Speichern der Daen meiner SDI-Anwendung.
Ich habe die Serialisierung nach Anleitung von Visual c++ in 21 Tagen aufgebaut, bekomme aber bei jedem versuch zu speichern eine Unbehandelte Ausnahme.

Aufbau:

C++:
// Klasse, die zu Serialisieren ist
//TODOSTRUCT.h
// TODOSTRUCT-Befehlsziel

class TODOSTRUCT : public CObject
{
DECLARE_SERIAL (TODOSTRUCT)
public:
    TODOSTRUCT();
    virtual ~TODOSTRUCT();
    TODOSTRUCT(const TODOSTRUCT &cop);
    //*** Operatoren
    TODOSTRUCT& TODOSTRUCT::operator = (const TODOSTRUCT &cop);
    //*** Methoden
    BOOL IsEmty();
    //*** Elemente
    int        iListPos;
    CString    szDateTime;
    CString szJob;
    CString szJobDescription;
    CString    szPriority;
    bool    bJobDone;
    virtual void Serialize(CArchive& ar);
};



C++:
//TODOSTRUCT.cpp
#include "TODOSTRUCT.h"

// TODOSTRUCT

IMPLEMENT_SERIAL(TODOSTRUCT,CObject,1)

TODOSTRUCT::TODOSTRUCT()
{
}

TODOSTRUCT::~TODOSTRUCT()
{
}

TODOSTRUCT::TODOSTRUCT(const TODOSTRUCT &cop)
{
    *this = cop;
}
//*** TODOSTRUCT-Memberfunktionen

void TODOSTRUCT::Serialize(CArchive& ar)
{
    if (ar.IsStoring())
    {    //*** storing code
        ar << iListPos;            //Listenposition
        ar << szDateTime;        //Datum Uhrzeit
        ar << szJob;            //Aufgabe
        ar << szJobDescription;    //Beschreibung
        ar << szPriority;        //Priorität
        ar << bJobDone;            //Erledigt
    }
    else
    {    //*** loading code
        ar >> iListPos;            //Listenposition
        ar >> szDateTime;        //Datum Uhrzeit
        ar >> szJob;            //Aufgabe
        ar >> szJobDescription;    //Beschreibung
        ar >> szPriority;        //Priorität
        ar >> bJobDone;            //Erledigt        
    }
}
//*** Operator =
TODOSTRUCT& TODOSTRUCT::operator = (const TODOSTRUCT &cop)
{
    this->iListPos = cop.iListPos;
    this->szDateTime = cop.szDateTime;
    this->szJob = cop.szJob;
    this->szJobDescription = cop.szJobDescription;
    this->szPriority = cop.szPriority;
    this->bJobDone = cop.bJobDone;
    return *this;
}



Habe in der Doc-Klasse der Anwendung eine CObjArray-Variable hinzugefügt, mit der ich die serialisierung anschupse.

C++:
//ToDoDoc.cpp
void CToDoDoc::Serialize(CArchive& ar)
{
    //*** Serialisierung an objArray weitergeben
    m_oaEntrys.Serialize(ar);
}



Der Fehler Tritt an dieser stelle auf:

C++:
//arcobj.cpp
void CArchive::WriteObject(const CObject* pOb)
{
    // object can be NULL

    ASSERT(IsStoring());    // proper direction

    if (!IsStoring())
    {
        AfxThrowArchiveException(CArchiveException::readOnly, m_strFileName);
    }

    DWORD nObIndex;
    ASSERT(sizeof(nObIndex) == 4);
    ASSERT(sizeof(wNullTag) == 2);
    ASSERT(sizeof(wBigObjectTag) == 2);
    ASSERT(sizeof(wNewClassTag) == 2);

    // make sure m_pStoreMap is initialized
    MapObject(NULL);

    if (pOb == NULL)
    {
        // save out null tag to represent NULL pointer
        *this << wNullTag;
    }
    else if ((nObIndex = (DWORD)(DWORD_PTR)(*m_pStoreMap)[(void*)pOb]) != 0)
        // assumes initialized to 0 map
    {
        // save out index of already stored object
        if (nObIndex < wBigObjectTag)
            *this << (WORD)nObIndex;
        else
        {
            *this << wBigObjectTag;
            *this << nObIndex;
        }
    }
    else
    {
        // write class of object first
        CRuntimeClass* pClassRef = pOb->GetRuntimeClass();  //Genau an dieser Stelle
        WriteClass(pClassRef);

        // enter in stored object table, checking for overflow
        CheckCount();
        (*m_pStoreMap)[(void*)pOb] = (void*)(DWORD_PTR)m_nMapCount++;

        // cause the object to serialize itself
        ((CObject*)pOb)->Serialize(*this);
    }
}



Hab ich vieleicht was vergessen oder hab ich was falsch gemacht.
Der Compiler meckert jedenfalls nicht.
--
Gruß GuenniAtWork

Dieser Post wurde am 12.07.2005 um 15:19 Uhr von GuenniAtWork editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
12.07.2005, 15:49 Uhr
Tommix



Hallo,
ObArrays sind ziehmlicher Müll, es ist besser, weil typsicher, CArray für den konkreten Typ zu spezialisieren. Möglicherweise ist in Deinem Array ein ungültiger Zeiger. Versuch mal

C++:
int size = m_oaEntrys.GetSize();

for (int i = 0; i< size; ++i)
    ASSERT_VALID(m_oaEntrys[i]);



Der Plural von entry ist btw entries.

- Tommix

Dieser Post wurde am 12.07.2005 um 15:50 Uhr von Tommix editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
12.07.2005, 23:05 Uhr
mmc20
puss in boots


hi,
wie tommix schon sagt, mach das array typsicher

C++:
    CTypedPtrArray<CObArray, TODOSTRUCT*> m_oaEntries;


zeig mal bitte den code wo du die objecte in das array speicherst, meistens ist da der fehler
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
13.07.2005, 12:20 Uhr
GuenniAtWork



Hi, Danke erstmal für die Tipps

Hier der Code

C++:
//*** Daten zum Dokument (ObjArray) hinzufügen
void CToDoDoc::InsertToDoStruct(TODOSTRUCT ToDoStruct, int nPos)
{
    m_oaEntries.SetAtGrow(nPos,ToDoStruct);
}

//*** Daten aus dem Document (ObjArray) entfernen
void CToDoDoc::DeleteToDoStructEntry(int nPos)
{
    //m_oaEntries.RemoveAt(nPos);
    for (int i = nPos; i < m_oaEntries.GetCount() - 1; ++i)
        m_oaEntries[i] = m_oaEntries[i+1];
}

//*** Document (ObjArray) leeren
void CToDoDoc::ClearDocument(void)
{
    m_oaEntries.RemoveAll();
}



@ Tommix:
Deinen Codeschnipsel hab ich mal ausprobiert.
Beim hinzufügen gabs keine ASSERTS aber beim löschen von Elementen.

Hab das Array zu nem CArray gemacht.
Bekomme jetzt keinen Fehler mehr beim speichern.
Mal sehen welcher der nächste ist

Mal so neben bei:
Was ist eigentlich der Unterschied zwischen GetSize() und GetCount() ?
--
Gruß GuenniAtWork
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
13.07.2005, 16:33 Uhr
GuenniAtWork



@ mmc20:
deine Methode hat nicht funktioniert. Da kam der selbe Fehler wie bei meiner eigenen Methode.

@ Tommix:
Das Speichern scheint zu funktionieren, dafür beim Öffnen. Ne Unbehabndelte Ausnahme (Was sonst)

Über die Serialisierung hole ich mir die Daten aus der datei:

C++:
//TODOSTRUCT.cpp
void TODOSTRUCT::Serialize(CArchive& ar)
{
    if (ar.IsStoring())
    {    //*** storing code
        ar << iListPos;            //Listenposition
        ar << szDateTime;        //Datum Uhrzeit
        ar << szJob;            //Aufgabe
        ar << szJobDescription;    //Beschreibung
        ar << szPriority;        //Priorität
        ar << bJobDone;            //Erledigt
    }
    else
    {    //*** loading code
        ar >> iListPos;            //Listenposition
        ar >> szDateTime;        //Datum Uhrzeit
        ar >> szJob;            //Aufgabe
        ar >> szJobDescription;    //Beschreibung
        ar >> szPriority;        //Priorität
        ar >> bJobDone;            //Erledigt        
    }
}


Dann sage ich meiner Viewklasse, sie soll die Daten anzeigen.
In OnOpenDocument:

C++:
//To-DoDoc.cpp
//*** Dokument öffnen
BOOL CToDoDoc::OnOpenDocument(LPCTSTR lpszPathName)
{
    if (!CDocument::OnOpenDocument(lpszPathName))
        return FALSE;

    POSITION pos = GetFirstViewPosition();
    CToDoView* pView = (CToDoView*)GetNextView(pos);
    pView->InitListView();

    return TRUE;
}


InitListView macht folgendes

C++:
//To-DoView.cpp
//*** Daten aus Dokument in ListView übertragen
void CToDoView::InitListView()
{
    CToDoDoc* pDoc = (CToDoDoc*)GetDocument();
    for (int i = 0; i < pDoc->GetEntriesCount(); ++i)
    {
        TODOSTRUCT OpenStruct = pDoc->GetEntry(i);  // Hier Unbehandelte Ausnahme
        //*** Referenz auf die Liste
        CListCtrl& ToDoList = GetListCtrl();
        int iPos = OpenStruct.iListPos;
        if (iPos >= 0)
        {
            //*** Item Anlegen
            ToDoList.InsertItem(iPos,OpenStruct.szDateTime);            //Datum
            //*** Daten in Felder schreiben
            ToDoList.SetItemText(iPos,1,OpenStruct.szJob);                //Aufgabe
            ToDoList.SetItemText(iPos,2,OpenStruct.szJobDescription);    //Beschreibung
            ToDoList.SetItemText(iPos,3,OpenStruct.szPriority);            //Priorität
            if (OpenStruct.bJobDone)
                ToDoList.SetItemText(iPos,4,_T("OK"));                    //Erledigt
            else
                ToDoList.SetItemText(iPos,4,_T(""));                    //nicht Erledigt
        }
    }
}


Hier was GetEntry macht

C++:
//To-DoDoc.cpp
//*** Ein Element aus dem CArray holen
TODOSTRUCT CToDoDoc::GetEntry(int nEntry)
{
    return  m_oaEntries[nEntry];
}



Bearbeitung von GuenniAtWork:

Ich habe ne meldung bekommen (einmal und niewieder): "out of memory".
(Wie zuwenig speicher??? Sind die 2GB schon voll???? )


--
Gruß GuenniAtWork

Dieser Post wurde am 13.07.2005 um 16:46 Uhr von GuenniAtWork editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
13.07.2005, 23:14 Uhr
mmc20
puss in boots


hi, dein insert funktioniert so nicht da du nur ein temporäres object hinzufügst, also zeigt der pointer danach irgendwo hin, bloss nicht auf ein gültiges object.

C++:
void CToDoDoc::InsertToDoStruct(TODOSTRUCT ToDoStruct, int nPos)
{
    m_oaEntries.SetAtGrow(nPos,ToDoStruct); // ToDoStruct ist zwar hier noch gültig
}
// aber hier schon nicht mehr...

// ich hab das mittels kopier-ctor gelöst und für das neue object eben
// auch neuen speicher "allokiert" (ok, ich nicht, new macht das... ;) )
void CToDoDoc::InsertToDoStruct(TODOSTRUCT ToDoStruct, int nPos)
{
    m_oaEntries.SetAtGrow(nPos, new TODOSTRUCT(ToDoStruct) );
}
// auf diese weisse hatte ich dann keine leaks mehr


dein delete sollte auch etwas anders aussehen, da du ja das element garnicht löscht sondern nur den pointer umkopierst, was dann wieder leaks produziert.
das removeall entfernt zwar die elemente des arrays, aber leider nicht die speicherzuweisung --> leaks

C++:
// laut MSDN solls so gehen
void CToDoDoc::DeleteToDoStructEntry(int nPos)
{
    TODOSTRUCT tmp = m_oaEntries.GetAt(nPos);
    m_oaEntries.RemoveAt(nPos); // RemoveAt kopiert selbst den rest des array
    delete tmp;
}

void CToDoDoc::ClearDocument()
{
    int i = 0;
    while ( i < m_oaEntries.GetSize() ) {
        delete m_oaEntries[i++];
    }
    m_oaEntries.RemoveAll();
}


Dieser Post wurde am 13.07.2005 um 23:16 Uhr von mmc20 editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
006
14.07.2005, 09:42 Uhr
GuenniAtWork



Moin!

Ich verwende keine Pointer in meinem Array


C++:
CArray<TODOSTRUCT> m_oaEntries;



Aber ich werde das mal mit nem CObArray versuchen
--
Gruß GuenniAtWork
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
007
14.07.2005, 09:58 Uhr
GuenniAtWork



Supi, mit dem CObArray hat das geklapt!

Nur bekomme ich, wenn ich ne gespeicherte Datei öffne nichts in meinem ListCtrl angezeigt.


C++:
//*** Daten aus Dokument in ListView übertragen
void CToDoView::InitListView()
{
    CToDoDoc* pDoc = (CToDoDoc*)GetDocument();
    for (int i = 0; i < pDoc->GetEntriesCount(); ++i)
    {
        TODOSTRUCT* OpenStruct = pDoc->GetEntry(i);
        //*** Referenz auf die Liste
        CListCtrl& ToDoList = GetListCtrl();
        int iPos = OpenStruct->iListPos;
        if (iPos >= 0)
        {
            //*** Item Anlegen
            ToDoList.InsertItem(iPos,OpenStruct->szDateTime);            //Datum
            //*** Daten in Felder schreiben
            ToDoList.SetItemText(iPos,1,OpenStruct->szJob);                //Aufgabe
            ToDoList.SetItemText(iPos,2,OpenStruct->szJobDescription);    //Beschreibung
            ToDoList.SetItemText(iPos,3,OpenStruct->szPriority);        //Priorität
            if (OpenStruct->bJobDone)
                ToDoList.SetItemText(iPos,4,_T("OK"));                    //Erledigt
            else
                ToDoList.SetItemText(iPos,4,_T(""));                    //nicht Erledigt
        }
    }
}



Ich bin mal schrittweise durchgegeangen und hab mir die Werte in OpenStruct angesehen, die sind in ordnung.
Aber warum fügt er die nicht ein bzw zeigt er sie nicht an????
--
Gruß GuenniAtWork
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
008
14.07.2005, 10:45 Uhr
xXx
Devil


wo legst du die columen an?!
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
009
14.07.2005, 11:16 Uhr
GuenniAtWork



In OnInitialUpdate(), oder gibts was besseres?


C++:
void CToDoView::OnInitialUpdate()
{
    CListView::OnInitialUpdate();

    // TODO: Sie können Elemente in Ihre ListView eintragen, indem Sie direkt
    //  über einen Aufruf von GetListCtrl() auf ihre Listensteuerung zugreifen.

    //***ListControl holen und Extended Styles setzen
    CListCtrl& ToDoList = GetListCtrl();
    ToDoList.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);
    
    //***Liste bereinigen
    ToDoList.DeleteAllItems();
    for(int i = 0; i < 4;++i)
        ToDoList.DeleteColumn(i);

    //***Spaltenüberschriften einfügen
    ToDoList.InsertColumn(0,"Zeitpunkt",LVCFMT_LEFT,150);    //Datum
    ToDoList.InsertColumn(1,"Aufgabe",LVCFMT_LEFT,200);        //Aufgabe
    ToDoList.InsertColumn(2,"Bemerkung",LVCFMT_LEFT,500);    //Bemerkung
    ToDoList.InsertColumn(3,"Priorität",LVCFMT_LEFT,100);    //Priorität
    ToDoList.InsertColumn(4,"Erledigt",LVCFMT_LEFT,100);    //Erledigt

    //*** Test Eintrag

}



Wenn ich über mein Kontextmenü was einfüge klapt das ohne Probleme.
--
Gruß GuenniAtWork

Dieser Post wurde am 14.07.2005 um 11:27 Uhr von GuenniAtWork editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 <     [ VC++ / MFC ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: